Compare commits

..

166 Commits
1.0.1 ... 1.1.1

Author SHA1 Message Date
Jeremy Ashkenas
d4d027159f rebuilding browser/source 2011-05-10 10:04:25 -04:00
Jeremy Ashkenas
a8a581acae Never return from a constructor. 2011-05-10 10:03:22 -04:00
Jeremy Ashkenas
9e4fa02cdb CoffeeScript 1.1.1 2011-05-10 09:27:19 -04:00
Jeremy Ashkenas
6d6e07604e Fixing external constructors / order of execution for once and for all ... knock on wood. 2011-05-10 09:24:20 -04:00
Michael Ficarra
f4b8e19c7f adding another failing test case related to #1182 2011-05-08 17:16:45 -04:00
Michael Ficarra
56b2b02637 some cleanup, renaming temporary variable from _by to _step 2011-05-06 23:10:46 -04:00
Michael Ficarra
d031c26229 Merge git://github.com/geraldalewis/coffee-script into geraldalewis_issue1326 2011-05-06 22:53:26 -04:00
Michael Ficarra
4046fcf971 adding failing test case for #1182 execution order bug mentioned by
@satyr
2011-05-06 09:48:12 -04:00
Michael Ficarra
7a4fd2ec01 slightly improved fix for #1182 and #1313 2011-05-06 09:47:40 -04:00
Michael Ficarra
73731ba155 Merge branch 'issue1313' 2011-05-06 01:10:27 -04:00
Michael Ficarra
8781a148db issues #1313 and #1182: better class compilation in presence of
externally defined constructors and inheritence via `extends`. Thanks to
@stephank for the suggested approach.
2011-05-06 01:00:35 -04:00
Gerald Lewis
0e978a0d99 Merge branch 'issue_1326' 2011-05-04 13:14:46 -04:00
Gerald Lewis
ac46ede170 Fix for #1326 by value is uncached 2011-05-04 13:12:05 -04:00
Satoshi Murakami
ad669fc23a command: JSLint => JavaScript Lint 2011-05-04 10:04:17 -07:00
Jeremy Ashkenas
71bcdb91c8 fixing changelog -- it was a regression from an earlier commit, not a true fix. 2011-05-01 14:29:48 -04:00
Jeremy Ashkenas
08294dc4d6 s/process.mainModule/require.main 2011-05-01 13:45:47 -04:00
Jeremy Ashkenas
09712603c4 coffee-script 1.1.0 2011-05-01 12:08:15 -04:00
Jeremy Ashkenas
2fb7ccc8f0 Revert "Fix for #1304 ... but disallows an alternative syntax."
This reverts commit 31bfe50831.
2011-05-01 10:43:50 -04:00
Jeremy Ashkenas
31bfe50831 Fix for #1304 ... but disallows an alternative syntax. 2011-05-01 10:16:04 -04:00
Jeremy Ashkenas
9aa3b5b78c showing line number information for failed tests. 2011-05-01 10:11:56 -04:00
Jeremy Ashkenas
7480f55e53 making end implicit tokens generated 2011-05-01 10:03:50 -04:00
Jeremy Ashkenas
5fd82e829b fixing test.html 2011-05-01 08:28:00 -04:00
Jeremy Ashkenas
43ebec1812 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-05-01 08:12:27 -04:00
Michael Ficarra
5cdf02f840 Merge pull request #1309 from TrevorBurnham/sandbox.
Fixing unavailability of `global` properties on REPL
2011-04-30 23:26:25 -07:00
Trevor Burnham
824e081005 Fixing unavailability of global properties on REPL 2011-05-01 01:45:14 -04:00
Trevor Burnham
fc992ba380 Using process.mainModule.filename instead of passing __filename 2011-04-30 23:01:36 -04:00
Trevor Burnham
264070bfc7 Making process.execPath point to coffee when running .coffee files
Related: #1303 set `process.argv[0]` to `coffee`. This makes
`process.execPath` consistent with that change.
2011-04-30 19:45:32 -04:00
Jeremy Ashkenas
a91509ba72 reintroducing a variant of kit's in-order script loading fix. 2011-04-30 13:48:54 -04:00
Jeremy Ashkenas
0dfe2429bc reverted @kitgoncharov's commits that broke the browser runner. 2011-04-30 13:33:28 -04:00
Jeremy Ashkenas
f1ad2e1fae Revert "Fix a typo in browser.coffee."
This reverts commit 6793eb383c.
2011-04-30 13:32:26 -04:00
Jeremy Ashkenas
c51679810a fixing unfoldSoak performance my memoizing. #1033 2011-04-30 13:13:09 -04:00
Jeremy Ashkenas
468ad1a2d5 Updating README and website with -g instructions. 2011-04-30 11:10:37 -04:00
Jeremy Ashkenas
bf8fbc2c0e Fixing process.argv[0] ... #1303 2011-04-30 10:59:55 -04:00
Jeremy Ashkenas
0ed8ae28e7 merging #1303 ... setting process.argv[0] to coffee for coffee's run. 2011-04-30 10:39:28 -04:00
Jeremy Ashkenas
f76ad8912c Merge pull request #1305 from benatkin/patch-1.
Updated for npm 1.0: the -g option installs to the global npm bin directory
2011-04-30 07:36:43 -07:00
Jeremy Ashkenas
83e7d442fb slightly less sketchy fix for #1106. 2011-04-30 10:35:56 -04:00
Jeremy Ashkenas
76252659fd Merge pull request #1300 from michaelficarra/issue1106.
fixes issue #1106
2011-04-30 07:29:41 -07:00
Ben Atkin
19036348a5 Updated for npm 1.0: the -g option installs to the global npm bin directory.
Without -g, the bin is in node-modules/.bin/coffee.
2011-04-29 19:57:18 -07:00
Michael Ficarra
7efea4bb23 removed "globals" option of CoffeeScript.compile and enhanced fix from
previous commits
2011-04-29 15:53:30 -04:00
Michael Ficarra
63ce244359 Better fixes for problem mentioned in last 3 commits. Also adds _
special value (as in node's REPL) that always holds return value of last
executed expression. Finally, fixes #1109
2011-04-29 13:59:59 -04:00
Michael Ficarra
0bdf9538d0 Recently discussed problem has been understood. Adding relevant values
to the global scope upon `eval` in REPL.

See bcf1e178a1 (commitcomment-362493)
2011-04-29 09:29:25 -04:00
Michael Ficarra
b88e23892f Fixes broken require from last commit. We're not actually sure yet
*why* `require` and only `require` was affected. All other globals that
I tried were unaffected: `console`, `parseInt`, `process`, `global`,
`Array`, `Object`, `Buffer`, `setTimeout`, ...
2011-04-29 09:18:47 -04:00
Michael Ficarra
bcf1e178a1 Fixes error in REPL where any variable defined in
`src/coffee-script.coffee` is shared with the REPL scope. Example: try
`lexer` or `@VERSION` pre-commit.
2011-04-29 02:32:16 -04:00
Trevor Burnham
fe889b8428 Setting process.argv[0] to 'coffee' in the REPL (aesthetic) 2011-04-28 18:35:42 -04:00
Trevor Burnham
cde7498c8e Setting process.argv[0] to 'coffee' in 'coffee foo.coffee'
See #1301 et al.
2011-04-28 18:27:40 -04:00
Jeremy Ashkenas
a27feb4157 Making the naming of the --join'd coffeescript mandatory. Issue #1076. 2011-04-27 23:06:58 -04:00
Jeremy Ashkenas
a93c835557 Issue #1006, infinite loop in addImplicitParentheses. 2011-04-27 22:49:42 -04:00
Michael Ficarra
5cd5821c18 #1106 test case: making sure __proto__ exists in case v8 ever removes it 2011-04-27 18:57:22 -07:00
Jeremy Ashkenas
3912e29eb7 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-04-27 21:56:31 -04:00
Jeremy Ashkenas
0bad04d374 Issue #1182 -- subclasses with external constructor functions. 2011-04-27 21:56:08 -04:00
Michael Ficarra
50c3a64553 fixes #1106; __proto__ compilation 2011-04-27 21:39:30 -04:00
Michael Ficarra
cd8492dd7b test for #1106 2011-04-27 21:36:29 -04:00
Jeremy Ashkenas
79e160a46b Edited documentation/index.html.erb via GitHub 2011-04-27 06:51:05 -07:00
Timothy Jones
761b3b3646 Merged pull request #1298 from pjaspers/patch-1.
Typo error, s/synax/syntax
2011-04-27 03:18:32 -07:00
Piet Jaspers
937f027f3c Typo error, s/synax/syntax 2011-04-27 00:57:37 -07:00
Jeremy Ashkenas
da14538299 Issue #1272 documentation 2011-04-26 21:47:48 -04:00
Jeremy Ashkenas
02fbf766ad removing erroneous tabs from nodes.coffee. 2011-04-26 21:23:51 -04:00
Jeremy Ashkenas
b13bef7f45 #1256, documentation typo 2011-04-26 20:46:07 -04:00
Jeremy Ashkenas
5e1aadba80 expanding on the sentence that talks about standalone extends ... Issue #1258 2011-04-26 20:42:24 -04:00
Jeremy Ashkenas
44e0bbf342 Issue #1262, print filename in error messages for require module scripts. 2011-04-26 20:35:30 -04:00
Jeremy Ashkenas
a7ed3379df merging in kit's in-order execution patch. 2011-04-23 13:40:40 -04:00
Jeremy Ashkenas
19849e66d4 renaming wordy test titles. 2011-04-23 13:35:15 -04:00
Jeremy Ashkenas
e9dac2fddc Fixes #1280, regex and compound division mixup. 2011-04-23 13:33:35 -04:00
Jeremy Ashkenas
e61fe48b4d Issue #1294, throw the error for a bad symlink reference when compiling a file. 2011-04-23 13:21:58 -04:00
Jeremy Ashkenas
7e8b52ad70 be more consistent about === 2011-04-20 23:43:41 -04:00
Jeremy Ashkenas
d5a5f9572e be consistent about triple-equals-equality. 2011-04-20 23:24:59 -04:00
Jeremy Ashkenas
fe4f7f8b0f Merge branch 'gh-pages' of https://github.com/willmoffat/coffee-script 2011-04-20 23:16:27 -04:00
Jeremy Ashkenas
4e3f80749f merging issue #1127 2011-04-20 23:12:05 -04:00
Jeremy Ashkenas
ff8c340330 Merge branch 'keyboard' of https://github.com/willmoffat/coffee-script 2011-04-20 23:10:48 -04:00
Jeremy Ashkenas
039109ed56 Removing resources section from the homepage, in favor of linking to the Wiki. #1137 2011-04-20 23:08:21 -04:00
Jeremy Ashkenas
f3f34e9ef5 Fixes #1188, scope for self-referencing functions. 2011-04-20 22:16:56 -04:00
Jeremy Ashkenas
2f39102026 merging fix for #1124 2011-04-18 20:44:27 -04:00
Kit Goncharov
6793eb383c Fix a typo in browser.coffee. 2011-04-11 13:50:27 -06:00
Kit Goncharov
2caceda8c4 Enforce script execution order in browser.coffee. 2011-04-11 13:38:38 -06:00
Jeremy Ashkenas
238dc3a5b6 merging in #1268 ... michaelficarra's colored REPL. 2011-04-09 17:42:03 -07:00
Jeremy Ashkenas
390ff30690 Merge branch 'stable' 2011-04-09 17:39:55 -07:00
Jeremy Ashkenas
e1cf187cfe Merge branch 'bugfix-1157' of https://github.com/thejh/coffee-script into stable 2011-04-09 16:11:21 -07:00
Jeremy Ashkenas
8c01df7828 Merge branch 'stable' 2011-04-09 16:02:10 -07:00
Jeremy Ashkenas
ff8faa4cd7 Merge branch 'stable' of github.com:jashkenas/coffee-script into stable 2011-04-09 16:01:20 -07:00
Jeremy Ashkenas
b9aa64fd25 merging in Josh's patch for Node 0.4.x module lookup changes. 2011-04-09 16:00:57 -07:00
Jeremy Ashkenas
8dfd53620c Merge branch 'module-loading' of https://github.com/josh/coffee-script into stable 2011-04-09 16:00:17 -07:00
Michael Ficarra
0090aee0e5 full revert of 4ce374be25 2011-04-09 10:48:14 -04:00
Michael Ficarra
230dea1243 fixes #1274: {}=a() and []=a() compile to false instead of a() 2011-04-09 09:54:45 -04:00
Michael Ficarra
3453bfa513 regression tests for #1274 2011-04-09 09:53:04 -04:00
Michael Ficarra
d0f047dfe7 improved fix for #1266 2011-04-07 19:40:45 -04:00
Michael Ficarra
8e7c454de0 disabling colours for win32 and in presence of NODE_DISABLE_COLORS
environment variable
2011-04-05 20:51:28 -04:00
Michael Ficarra
68c75c7eb1 pretty node-like output in the REPL 2011-04-05 20:40:54 -04:00
Michael Ficarra
31ae260282 unnecessarily strict {in,}equality in existence checks 2011-03-29 17:25:09 -04:00
Jann Horn
8b443b94ea added a test 2011-03-28 23:16:49 +02:00
Jann Horn
6ec9c844e4 fixes #1124 (and uglifies generated JS) 2011-03-28 23:12:27 +02:00
Jeremy Ashkenas
3d3b03e1e4 Merge branch 'stable' of github.com:jashkenas/coffee-script into stable 2011-03-28 08:37:15 -04:00
Jeremy Ashkenas
4d194cb50c rebuilt parser with Jison 0.2.4 2011-03-28 08:36:42 -04:00
Michael Ficarra
b0d2bf4afe Merge branch 'improvedRangeCompilation' of github.com:michaelficarra/coffee-script into michaelficarra-improvedRangeCompilation 2011-03-28 00:51:42 -04:00
Michael Ficarra
8f73bc3b4c Merge branch 'bugfix-1108' of https://github.com/thejh/coffee-script into thejh-bugfix-1108 2011-03-27 23:54:46 -04:00
Michael Ficarra
90495b614f Merge branch 'thejh-bugfix-1099' into stable 2011-03-27 23:47:01 -04:00
Michael Ficarra
f03bcc24ad enhanced tests for #1099 fix 2011-03-27 23:42:49 -04:00
Jann Horn
6646155712 fixes #1157: when compiling multiple scripts, compile them if at least one of them isn't empty 2011-03-27 23:30:55 +02:00
Jann Horn
9d72208d9e added a test (issue #1099) 2011-03-27 21:35:29 +02:00
Jann Horn
e84e703211 fixes bug mentioned by @satyr in #1108
"[v] = a ? b" must compile to
v = (typeof a != "undefined" && a !== null ? a : b)[0];
and not to:
v = typeof a != "undefined" && a !== null ? a : b[0];
2011-03-27 21:22:09 +02:00
Jann Horn
0497c0742f fixes #1099: instead of nothing, compile to false
"if a in []"
2011-03-27 19:46:44 +02:00
Joshua Peek
573e2b0012 Assign module.paths for node_module loading 2011-03-25 15:36:48 -05:00
Michael Ficarra
c4b72fcc79 improved range compilation 2011-03-23 13:49:15 -04:00
Jeremy Ashkenas
a2d7716331 Adding CoffeeScript.mode 2011-03-20 17:40:20 -04:00
Will Moffat
67b5ebdb76 Bind not required for evalJS. 2011-03-19 16:03:53 -07:00
Will Moffat
4c2ce2b45b Merge branch 'master' of https://github.com/jashkenas/coffee-script into keyboard 2011-03-19 15:28:50 -07:00
Jeremy Ashkenas
3b2bade2f2 Use the newer Node.js binding for 'vm'. 2011-03-16 05:47:58 -05:00
Jeremy Ashkenas
cdeb28a793 missing space. 2011-03-16 05:45:17 -05:00
Jeremy Ashkenas
61918a1efa merging stable 2011-03-12 07:41:58 -06:00
Jeremy Ashkenas
963adb5230 merging jcoglan's splat declaration patch. 2011-03-12 07:41:14 -06:00
Jeremy Ashkenas
8f8a1ecf18 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-03-12 07:38:34 -06:00
James Coglan
b9343b458f Fix scoping of splat parameters in argument lists. 2011-03-12 11:46:07 +00:00
Jeremy Ashkenas
ac85fa2fc3 merged stable 2011-03-11 22:44:18 -05:00
Jeremy Ashkenas
b7855857b5 stop trimming all trailing whitespace. 2011-03-11 22:39:32 -05:00
Jeremy Ashkenas
d957c4373b test-ified function_invocation 2011-03-11 22:18:22 -05:00
Jeremy Ashkenas
f485d8f548 test-ified control_flow 2011-03-11 22:09:33 -05:00
Jeremy Ashkenas
b994e235f3 test-ified comprehensions.coffee 2011-03-11 22:05:52 -05:00
Jeremy Ashkenas
2b1aea80ed testified compilation.coffee, removed empty command.coffee 2011-03-11 21:59:17 -05:00
Jeremy Ashkenas
53d8083343 removing empty test file for cake.coffee 2011-03-11 21:55:43 -05:00
Jeremy Ashkenas
d30c125ab7 continuing with the ol' refactorTests 2011-03-11 21:55:26 -05:00
Jeremy Ashkenas
9e2c75b548 removing over-hash-comment 2011-03-11 21:41:12 -05:00
Michael Ficarra
aa54b23713 fixes #1168: leading floating point suppresses newline (thanks, satyr) 2011-02-27 02:11:35 -05:00
Michael Ficarra
dc8e955c4f test for #1168 2011-02-27 02:11:12 -05:00
Timothy Jones
96b22a16eb Closes #1001. Throw cannot be directly used as an expression with parens, but can appear as a statement in an expression. 2011-02-23 15:50:28 +13:00
Timothy Jones
5fbbfbcbe3 Closes #1082. Puts back use of function calls in parameter lists. 2011-02-23 13:20:01 +13:00
Jeremy Ashkenas
faf98dacf6 stricter array splat tests. 2011-02-18 07:15:40 -05:00
Jeremy Ashkenas
86b47a528a adding an array splat test. 2011-02-17 21:56:28 -05:00
Jeremy Ashkenas
cf6c21a0d2 merging in aeosynth's tweaks to package.json 2011-02-17 21:21:31 -05:00
James Campos
b1d900210a add repository to package.json 2011-02-10 18:17:53 -08:00
James Campos
963fc4cebc add homepage to package.json 2011-02-10 17:54:00 -08:00
Will Moffat
80adaa700c Console keyboard shortcuts
Cmd/Ctrl-Enter to run code
Escape to dismiss console
2011-02-10 08:40:53 -08:00
Will Moffat
dfead460ca Disable spellcheck in the code editor.
Firefox highlights all the camelCase variable names in the examples and even WebKit highligts words like 'bitlist'.
2011-02-09 15:52:35 -08:00
Jeremy Ashkenas
6f21f8a402 merging stable 2011-02-01 22:02:57 -05:00
Trevor Burnham
abfc99308d Setting process.argv[1] to equal the filename of the script being run (issue 1087) 2011-02-01 21:41:20 -05:00
Jeremy Ashkenas
955c87ef30 Bumping version to 1.0.2-pre 2011-02-01 21:32:58 -05:00
Jeremy Ashkenas
b4df62bec1 #1085, adding CoffeeScript.mode to the docs. 2011-02-01 21:31:54 -05:00
Jeremy Ashkenas
14d2fa3895 #1085, adding CoffeeScript.mode to the docs. 2011-02-01 21:30:33 -05:00
Jeremy Ashkenas
005c5309c4 Merging in stable at 1.0.1 2011-01-31 23:34:34 -05:00
Jeremy Ashkenas
3c9fdde24b resolved merge 2011-01-30 19:40:59 -05:00
Jeremy Ashkenas
654c933e30 fixing version number to 1.1.0-pre ... to make it installable with npm. 2011-01-30 17:00:07 -05:00
Timothy Jones
83a86aacb5 Closes #1068. Don't know why CALL_START was in that file. 2011-01-24 19:57:31 +13:00
Timothy Jones
f231809e22 Swapping == with <, just in case. 2011-01-23 00:54:43 +13:00
Timothy Jones
2c8e0a6914 Merge branch 'readline0.3.6' of https://github.com/agnoster/coffee-script into agnoster 2011-01-23 00:43:18 +13:00
Isaac Wolkerstorfer
496816acff Add backwards compatibility for older readline
Check the readline.createInterface for arity. If it is 3,
assume the newer interface requiring separate stdin and stdout.
Otherwise, use the older calling style.
2011-01-22 12:30:22 +01:00
Isaac Wolkerstorfer
78b52f5716 Replace stdio with stdin/stdout pair for readline
On Node.js v0.3.6, the readline interface expects (in, out, complete).
This change makes the coffee-script repl conform to that expectation.
2011-01-22 11:40:25 +01:00
Timothy Jones
2ca108820f Closes #973. New is more careful around the do construct. 2011-01-22 23:26:38 +13:00
Timothy Jones
dc6bd715b2 Closes #970. Statements that use new are wrapped in parens to avoid the closure being used. 2011-01-22 23:12:39 +13:00
Timothy Jones
18a1e01d64 Closes #971. Existensial slices now supported. 2011-01-22 19:56:14 +13:00
Timothy Jones
15e1078d01 I suppose there's no reason to ever call a prototype like a function. 2011-01-22 19:34:30 +13:00
Timothy Jones
06b0c7e928 Closes #1064. Dot accesses force the next token to be an identifier. 2011-01-22 19:29:07 +13:00
Jeremy Ashkenas
3924c2f2bd First draft of fixing shorthand objects mixed with regulars within arrays. 2011-01-19 22:36:30 -05:00
Jeremy Ashkenas
7625d900d3 toTimeString -> toLocaleTimeString 2011-01-19 22:17:53 -05:00
Jeremy Ashkenas
53dc1f2055 Merging in donjones' implicit object fix, hooray. 2011-01-18 23:46:55 -05:00
Jeremy Ashkenas
e706fa4a58 Merge branch 'master' of https://github.com/donjones/coffee-script 2011-01-18 23:38:22 -05:00
Jeremy Ashkenas
65e81e4034 Merge branch '1.0-stable' 2011-01-18 23:29:44 -05:00
Jeremy Ashkenas
4b78790096 Making #1050 a syntax error. 2011-01-18 23:10:09 -05:00
Jonas Dohse
236e129e7a Tests for call parameters after implicit objects 2011-01-19 00:32:59 +01:00
Jonas Dohse
d200619774 Check for invalid implicit values 2011-01-18 23:31:50 +01:00
Jonas Dohse
d0f13223bc No assignment shortcut in implicit braces
Let

    f a: b, c

compile to

    f({
      a: b
    }, c);
2011-01-18 15:42:59 +01:00
Jeremy Ashkenas
7ae284f432 Allowing an environment variable of MINIFY=false to disable minification of the build:browser cake task. 2011-01-15 15:20:01 -05:00
Jeremy Ashkenas
df872b8223 Merge branch '1.0-stable' 2011-01-15 15:15:33 -05:00
Jeremy Ashkenas
d8823ed45e Implemented continuable lines in the REPL. Use a trailing slash. Multiline functions are now possible. 2011-01-15 15:06:51 -05:00
Jeremy Ashkenas
9a63b3147f First implementation of autocomplete. 2011-01-15 14:53:07 -05:00
Jeremy Ashkenas
3f586ff4ab Merge branch 'master' into 1.1-pre 2011-01-15 14:50:44 -05:00
Jeremy Ashkenas
c4d4cfe9dc Merge branch 'master' of https://github.com/ryszard/coffee-script into 1.1-pre 2011-01-15 14:50:41 -05:00
Jeremy Ashkenas
9faedbf516 bump version to 1.1-pre 2011-01-15 10:28:26 -05:00
Ryszard Szopa
bb745a8036 Basic REPL autocomplete.
It sort of works, but the tests could are incomplete.
2010-12-29 12:59:23 +01:00
67 changed files with 2947 additions and 2204 deletions

View File

@@ -94,15 +94,16 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
#{fs.readFileSync "lib/#{name}.js"}
};
"""
{parser, uglify} = require 'uglify-js'
ast = parser.parse """
code = """
this.CoffeeScript = function() {
function require(path){ return require[path]; }
#{code}
return require['./coffee-script']
}()
"""
code = uglify.gen_code uglify.ast_squeeze uglify.ast_mangle ast, extra: yes
unless process.env.MINIFY is 'false'
{parser, uglify} = require 'uglify-js'
code = uglify.gen_code uglify.ast_squeeze uglify.ast_mangle parser.parse code
fs.writeFileSync 'extras/coffee-script.js', header + '\n' + code
console.log "built ... running browser tests:"
invoke 'test:browser'
@@ -203,6 +204,7 @@ runTests = (CoffeeScript) ->
{error, file} = fail
jsFile = file.replace(/\.coffee$/,'.js')
match = error.stack?.match(new RegExp(fail.file+":(\\d+):(\\d+)"))
match = error.stack?.match(/on line (\d+):/) unless match
[match, line, col] = match if match
log "\n #{error.toString()}", red
log " #{error.description}", red if error.description

3
README
View File

@@ -26,7 +26,8 @@
sudo bin/cake install
Or, if you have the Node Package Manager installed:
npm install coffee-script
npm install -g coffee-script
(Leave off the -g if you don't wish to install globally.)
Compile a script:
coffee /path/to/script.coffee

View File

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

View File

@@ -2,21 +2,32 @@
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-&gt;</span>
<span class="nv">options.bare = </span><span class="kc">on</span>
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="nx">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="nx">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">xhr = </span><span class="k">new</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span> <span class="o">or</span> <span class="nx">XMLHttpRequest</span><span class="p">)(</span><span class="s1">&#39;Microsoft.XMLHTTP&#39;</span><span class="p">)</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s1">&#39;text/plain&#39;</span> <span class="k">if</span> <span class="s1">&#39;overrideMimeType&#39;</span> <span class="k">of</span> <span class="nx">xhr</span>
<span class="nv">xhr.onreadystatechange = </span><span class="o">-&gt;</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">,</span> <span class="nx">options</span> <span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">]</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span>
<span class="k">else</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;Could not load #{url}&quot;</span>
<span class="nx">callback</span><span class="p">()</span> <span class="k">if</span> <span class="nx">callback</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>.
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">runScripts = </span><span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">script</span> <span class="k">in</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s1">&#39;script&#39;</span>
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">&#39;text/coffeescript&#39;</span>
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s1">&#39;script&#39;</span>
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">&#39;text/coffeescript&#39;</span><span class="p">)</span>
<span class="nv">index = </span><span class="mi">0</span>
<span class="nv">length = </span><span class="nx">coffees</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">do</span> <span class="nv">execute = </span><span class="o">-&gt;</span>
<span class="nv">script = </span><span class="nx">coffees</span><span class="p">[</span><span class="nx">index</span><span class="o">++</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">&#39;text/coffeescript&#39;</span>
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span><span class="p">,</span> <span class="nx">execute</span>
<span class="k">else</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span>
<span class="nx">execute</span><span class="p">()</span>
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Listen for window load, both in browsers and in IE.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
<span class="nx">addEventListener</span> <span class="s1">&#39;DOMContentLoaded&#39;</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>
<span class="k">else</span>

View File

@@ -6,13 +6,14 @@ source CoffeeScript into JavaScript.</p>
<p>If included on a webpage, it will automatically sniff out, compile, and
execute all scripts present in <code>text/coffeescript</code> tags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">&#39;fs&#39;</span>
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">&#39;path&#39;</span>
<span class="nv">vm = </span><span class="nx">require</span> <span class="s1">&#39;vm&#39;</span>
<span class="p">{</span><span class="nx">Lexer</span><span class="p">,</span><span class="nx">RESERVED</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;./lexer&#39;</span>
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;./parser&#39;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>TODO: Remove registerExtension when fully deprecated.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="s1">&#39;.coffee&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">filename</span><span class="p">,</span> <span class="s1">&#39;utf8&#39;</span>
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">filename</span><span class="p">,</span> <span class="s1">&#39;utf8&#39;</span><span class="p">),</span> <span class="p">{</span><span class="nx">filename</span><span class="p">}</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">content</span><span class="p">,</span> <span class="nx">filename</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">&#39;.coffee&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s1">&#39;1.0.1&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Words that cannot be used as identifiers in CoffeeScript code</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RESERVED = </span><span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s1">&#39;./helpers&#39;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">&#39;.coffee&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s1">&#39;1.1.1&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Words that cannot be used as identifiers in CoffeeScript code</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RESERVED = </span><span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s1">&#39;./helpers&#39;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-&gt;</span>
<span class="k">try</span>
<span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
@@ -28,14 +29,26 @@ or traverse it by using <code>.traverse()</code> with a callback.</p>
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>We want the root module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root = </span><span class="nx">module</span>
<span class="k">while</span> <span class="nx">root</span><span class="p">.</span><span class="nx">parent</span>
<span class="nv">root = </span><span class="nx">root</span><span class="p">.</span><span class="nx">parent</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root.filename = </span><span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;.&#39;</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root.moduleCache = </span><span class="p">{}</span> <span class="k">if</span> <span class="nx">root</span><span class="p">.</span><span class="nx">moduleCache</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">root</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;.coffee&#39;</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="nv">root = </span><span class="nx">root</span><span class="p">.</span><span class="nx">parent</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;.&#39;</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root.moduleCache = </span><span class="p">{}</span> <span class="k">if</span> <span class="nx">root</span><span class="p">.</span><span class="nx">moduleCache</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">process</span><span class="p">.</span><span class="nx">binding</span><span class="p">(</span><span class="s1">&#39;natives&#39;</span><span class="p">).</span><span class="nx">module</span>
<span class="p">{</span><span class="nx">Module</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;module&#39;</span>
<span class="nv">root.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">root</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;.coffee&#39;</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="nx">root</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">root</span><span class="p">.</span><span class="nx">filename</span>
<span class="k">else</span>
<span class="nx">root</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">root</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">__filename = module.filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
<span class="nv">__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">__filename</span>
<span class="nb">eval</span> <span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
<span class="nx">root</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">root</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-&gt;</span>
<span class="nv">sandbox = </span><span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
<span class="nx">unless</span> <span class="nx">sandbox</span>
<span class="nv">sandbox =</span>
<span class="nx">require</span><span class="o">:</span> <span class="nx">require</span>
<span class="nx">module</span> <span class="o">:</span> <span class="p">{</span> <span class="nx">exports</span><span class="o">:</span> <span class="p">{}</span> <span class="p">}</span>
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="o">=</span> <span class="nx">global</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="k">for</span> <span class="nx">g</span> <span class="k">of</span> <span class="nx">global</span>
<span class="nv">sandbox.global = </span><span class="nx">sandbox</span>
<span class="nv">sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = </span><span class="nx">sandbox</span>
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s1">&#39;eval&#39;</span>
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span>
<span class="nv">js = </span><span class="nx">compile</span> <span class="s2">&quot;_=(#{code.trim()})&quot;</span><span class="p">,</span> <span class="nx">options</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInNewContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span><span class="p">,</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
thin wrapper around it, compatible with the Jison API. We can then pass it
directly as a "Jison lexer".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parser.lexer =</span>
<span class="nx">lex</span><span class="o">:</span> <span class="o">-&gt;</span>

View File

@@ -1,6 +1,6 @@
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
into various forms: saved into <code>.js</code> files or printed to stdout, piped to
<a href="http://javascriptlint.com/">JSLint</a> or recompiled every time the source is
<a href="http://javascriptlint.com/">JavaScript Lint</a> or recompiled every time the source is
saved, printed as a token stream or as the syntax tree, or launch an
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">&#39;fs&#39;</span>
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">&#39;path&#39;</span>
@@ -17,10 +17,10 @@ interactive REPL.</p> </td> <td class="code">
<span class="p">[</span><span class="s1">&#39;-c&#39;</span><span class="p">,</span> <span class="s1">&#39;--compile&#39;</span><span class="p">,</span> <span class="s1">&#39;compile to JavaScript and save as .js files&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-i&#39;</span><span class="p">,</span> <span class="s1">&#39;--interactive&#39;</span><span class="p">,</span> <span class="s1">&#39;run an interactive CoffeeScript REPL&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-o&#39;</span><span class="p">,</span> <span class="s1">&#39;--output [DIR]&#39;</span><span class="p">,</span> <span class="s1">&#39;set the directory for compiled JavaScript&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-j&#39;</span><span class="p">,</span> <span class="s1">&#39;--join&#39;</span><span class="p">,</span> <span class="s1">&#39;concatenate the scripts before compiling&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-j&#39;</span><span class="p">,</span> <span class="s1">&#39;--join [FILE]&#39;</span><span class="p">,</span> <span class="s1">&#39;concatenate the scripts before compiling&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-w&#39;</span><span class="p">,</span> <span class="s1">&#39;--watch&#39;</span><span class="p">,</span> <span class="s1">&#39;watch scripts for changes, and recompile&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-p&#39;</span><span class="p">,</span> <span class="s1">&#39;--print&#39;</span><span class="p">,</span> <span class="s1">&#39;print the compiled JavaScript to stdout&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-l&#39;</span><span class="p">,</span> <span class="s1">&#39;--lint&#39;</span><span class="p">,</span> <span class="s1">&#39;pipe the compiled JavaScript through JSLint&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-l&#39;</span><span class="p">,</span> <span class="s1">&#39;--lint&#39;</span><span class="p">,</span> <span class="s1">&#39;pipe the compiled JavaScript through JavaScript Lint&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-s&#39;</span><span class="p">,</span> <span class="s1">&#39;--stdio&#39;</span><span class="p">,</span> <span class="s1">&#39;listen for and compile scripts over stdio&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-e&#39;</span><span class="p">,</span> <span class="s1">&#39;--eval&#39;</span><span class="p">,</span> <span class="s1">&#39;compile a string from the command line&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-r&#39;</span><span class="p">,</span> <span class="s1">&#39;--require [FILE*]&#39;</span><span class="p">,</span> <span class="s1">&#39;require a library before executing your script&#39;</span><span class="p">]</span>
@@ -48,6 +48,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span>
<span class="nv">opts.literals = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="nx">concat</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">literals</span>
<span class="nv">process.ARGV = process.argv = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">concat</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">literals</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;coffee&#39;</span>
<span class="nv">process.execPath = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span><span class="p">.</span><span class="nx">filename</span>
<span class="nx">compileScripts</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Asynchronously read in each CoffeeScript in a list of source files and
compile them. If a directory is passed, recursively compile all
'.coffee' extension source files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScripts = </span><span class="o">-&gt;</span>
@@ -57,6 +59,7 @@ compile them. If a directory is passed, recursively compile all
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;File not found: #{source}&quot;</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">exists</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">stats</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">files</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span>
@@ -65,7 +68,7 @@ compile them. If a directory is passed, recursively compile all
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
<span class="nx">contents</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span><span class="p">]</span> <span class="o">=</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
<span class="nx">compileJoin</span><span class="p">()</span> <span class="k">if</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">compact</span><span class="p">(</span><span class="nx">contents</span><span class="p">).</span><span class="nx">length</span> <span class="o">is</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">compileJoin</span><span class="p">()</span> <span class="k">if</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">compact</span><span class="p">(</span><span class="nx">contents</span><span class="p">).</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
<span class="k">else</span>
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
@@ -101,7 +104,7 @@ and write them back to <strong>stdout</strong>.</p> </td>
<span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>After all of the source files are done being read, concatenate and compile
them together.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileJoin = </span><span class="o">-&gt;</span>
<span class="nv">code = </span><span class="nx">contents</span><span class="p">.</span><span class="nx">join</span> <span class="s1">&#39;\n&#39;</span>
<span class="nx">compileScript</span> <span class="s2">&quot;concatenation&quot;</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="s2">&quot;concatenation&quot;</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Load files that are to-be-required before compilation occurs.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadRequires = </span><span class="o">-&gt;</span>
<span class="nx">compileScript</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Load files that are to-be-required before compilation occurs.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadRequires = </span><span class="o">-&gt;</span>
<span class="nv">realFilename = </span><span class="nx">module</span><span class="p">.</span><span class="nx">filename</span>
<span class="nv">module.filename = </span><span class="s1">&#39;.&#39;</span>
<span class="nx">require</span> <span class="nx">req</span> <span class="k">for</span> <span class="nx">req</span> <span class="k">in</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">require</span>
@@ -126,7 +129,7 @@ directory can be customized with <code>--output</code>.</p> </td>
<span class="k">if</span> <span class="nx">err</span>
<span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;#{(new Date).toTimeString()} - compiled #{source}&quot;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;#{(new Date).toLocaleTimeString()} - compiled #{source}&quot;</span>
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">dir</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">&quot;mkdir -p #{dir}&quot;</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">js</span><span class="p">)</span> <span class="o">-&gt;</span>

View File

@@ -160,11 +160,15 @@ or by array index or slice.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s1">&#39;:: Identifier&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">&#39;proto&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;::&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;prototype&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Index&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Slice&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Slice</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Index</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_START Expression INDEX_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Index</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_START IndexValue INDEX_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_SOAK Index&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">extend</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">soak</span> <span class="o">:</span> <span class="kc">yes</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_PROTO Index&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">extend</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">proto</span><span class="o">:</span> <span class="kc">yes</span>
<span class="p">]</span>
<span class="nx">IndexValue</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Index</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Slice&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Slice</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p>In CoffeeScript, an object literal is simply a list of assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Object</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;{ AssignList OptComma }&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Obj</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">generated</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>Assignment of properties within an object literal can be separated by
@@ -209,9 +213,9 @@ and optional references to the superclass.</p> </td> <td
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Range</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;[ Expression RangeDots Expression ]&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>Array slice literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Slice</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_START Expression RangeDots Expression INDEX_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_START Expression RangeDots INDEX_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;INDEX_START RangeDots Expression INDEX_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;Expression RangeDots Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;Expression RangeDots&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;RangeDots Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">&#182;</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
as well as the contents of an array literal
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ArgList</span><span class="o">:</span> <span class="p">[</span>

View File

@@ -58,7 +58,8 @@ though <code>is</code> means <code>===</code> otherwise.</p> </td>
<span class="nx">@token</span> <span class="s1">&#39;OWN&#39;</span><span class="p">,</span> <span class="nx">id</span>
<span class="k">return</span> <span class="nx">id</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">forcedIdentifier = </span><span class="nx">colon</span> <span class="o">or</span>
<span class="p">(</span><span class="nv">prev = </span><span class="nx">last</span> <span class="nx">@tokens</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;.&#39;</span><span class="p">,</span> <span class="s1">&#39;?.&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;::&#39;</span><span class="p">]</span>
<span class="p">(</span><span class="nv">prev = </span><span class="nx">last</span> <span class="nx">@tokens</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;.&#39;</span><span class="p">,</span> <span class="s1">&#39;?.&#39;</span><span class="p">,</span> <span class="s1">&#39;::&#39;</span><span class="p">]</span> <span class="o">or</span>
<span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;@&#39;</span><span class="p">)</span>
<span class="nv">tag = </span><span class="s1">&#39;IDENTIFIER&#39;</span>
<span class="k">if</span> <span class="nx">id</span> <span class="k">in</span> <span class="nx">JS_KEYWORDS</span> <span class="o">or</span>
@@ -91,7 +92,7 @@ though <code>is</code> means <code>===</code> otherwise.</p> </td>
<span class="nx">@identifierError</span> <span class="nx">id</span>
<span class="nx">unless</span> <span class="nx">forcedIdentifier</span>
<span class="nv">id = </span><span class="nx">COFFEE_ALIASES</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span> <span class="k">if</span> <span class="nx">COFFEE_ALIASES</span><span class="p">.</span><span class="nx">hasOwnProperty</span> <span class="nx">id</span>
<span class="nv">id = </span><span class="nx">COFFEE_ALIAS_MAP</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span> <span class="k">if</span> <span class="nx">id</span> <span class="k">in</span> <span class="nx">COFFEE_ALIASES</span>
<span class="nv">tag = </span><span class="k">switch</span> <span class="nx">id</span>
<span class="k">when</span> <span class="s1">&#39;!&#39;</span> <span class="k">then</span> <span class="s1">&#39;UNARY&#39;</span>
<span class="k">when</span> <span class="s1">&#39;==&#39;</span><span class="p">,</span> <span class="s1">&#39;!=&#39;</span> <span class="k">then</span> <span class="s1">&#39;COMPARE&#39;</span>
@@ -136,11 +137,11 @@ preserve whitespace, but ignore indentation to the left.</p> </td>
<span class="nx">heredoc</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Matches and consumes comments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">commentToken</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="mi">0</span> <span class="nx">unless</span> <span class="nv">match = </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">COMMENT</span>
<span class="p">[</span><span class="nx">comment</span><span class="p">,</span> <span class="nx">here</span><span class="p">]</span> <span class="o">=</span> <span class="nx">match</span>
<span class="nx">@line</span> <span class="o">+=</span> <span class="nx">count</span> <span class="nx">comment</span><span class="p">,</span> <span class="s1">&#39;\n&#39;</span>
<span class="k">if</span> <span class="nx">here</span>
<span class="nx">@token</span> <span class="s1">&#39;HERECOMMENT&#39;</span><span class="p">,</span> <span class="nx">@sanitizeHeredoc</span> <span class="nx">here</span><span class="p">,</span>
<span class="nx">herecomment</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">indent</span><span class="o">:</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">@indent</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
<span class="nx">@token</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;\n&#39;</span>
<span class="nx">@line</span> <span class="o">+=</span> <span class="nx">count</span> <span class="nx">comment</span><span class="p">,</span> <span class="s1">&#39;\n&#39;</span>
<span class="nx">comment</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Matches JavaScript interpolated directly into the source via backticks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">jsToken</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="mi">0</span> <span class="nx">unless</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;`&#39;</span> <span class="o">and</span> <span class="nv">match = </span><span class="nx">JSTOKEN</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">@chunk</span>
<span class="nx">@token</span> <span class="s1">&#39;JS&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nv">script = </span><span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">]).</span><span class="nx">slice</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
@@ -277,8 +278,11 @@ parentheses that indicate a method call from regular parentheses, and so on.</p>
<span class="nx">value</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <h2>Token Manipulators</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Sanitize a heredoc or herecomment by
erasing all external indentation on the left-hand side.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">sanitizeHeredoc</span><span class="o">:</span> <span class="p">(</span><span class="nx">doc</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">{</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">herecomment</span><span class="p">}</span> <span class="o">=</span> <span class="nx">options</span>
<span class="k">return</span> <span class="nx">doc</span> <span class="k">if</span> <span class="nx">herecomment</span> <span class="o">and</span> <span class="mi">0</span> <span class="o">&gt;</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">&#39;\n&#39;</span>
<span class="nx">unless</span> <span class="nx">herecomment</span>
<span class="k">if</span> <span class="nx">herecomment</span>
<span class="k">if</span> <span class="nx">HEREDOC_ILLEGAL</span><span class="p">.</span><span class="nx">test</span> <span class="nx">doc</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;block comment cannot contain \&quot;*/\&quot;, starting on line #{@line + 1}&quot;</span>
<span class="k">return</span> <span class="nx">doc</span> <span class="k">if</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;\n&#39;</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">0</span>
<span class="k">else</span>
<span class="k">while</span> <span class="nv">match = </span><span class="nx">HEREDOC_INDENT</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">doc</span>
<span class="nv">attempt = </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nv">indent = </span><span class="nx">attempt</span> <span class="k">if</span> <span class="nx">indent</span> <span class="o">is</span> <span class="kc">null</span> <span class="o">or</span> <span class="mi">0</span> <span class="o">&lt;</span> <span class="nx">attempt</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
@@ -298,7 +302,7 @@ parameters specially in order to make things easier for the parser.</p>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">tok</span>
<span class="k">when</span> <span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_START&#39;</span>
<span class="k">if</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="k">else</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;(&#39;</span>
<span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;PARAM_START&#39;</span>
<span class="k">return</span> <span class="k">this</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Close up all remaining open blocks at the end of the file.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeIndentation</span><span class="o">:</span> <span class="o">-&gt;</span>
@@ -394,7 +398,8 @@ token stream.</p> </td> <td class="code">
<span class="s1">&#39;if&#39;</span><span class="p">,</span> <span class="s1">&#39;else&#39;</span><span class="p">,</span> <span class="s1">&#39;switch&#39;</span><span class="p">,</span> <span class="s1">&#39;for&#39;</span><span class="p">,</span> <span class="s1">&#39;while&#39;</span><span class="p">,</span> <span class="s1">&#39;do&#39;</span><span class="p">,</span> <span class="s1">&#39;try&#39;</span><span class="p">,</span> <span class="s1">&#39;catch&#39;</span><span class="p">,</span> <span class="s1">&#39;finally&#39;</span>
<span class="s1">&#39;class&#39;</span><span class="p">,</span> <span class="s1">&#39;extends&#39;</span><span class="p">,</span> <span class="s1">&#39;super&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">&#182;</a> </div> <p>CoffeeScript-only keywords.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">COFFEE_KEYWORDS = </span><span class="p">[</span><span class="s1">&#39;undefined&#39;</span><span class="p">,</span> <span class="s1">&#39;then&#39;</span><span class="p">,</span> <span class="s1">&#39;unless&#39;</span><span class="p">,</span> <span class="s1">&#39;until&#39;</span><span class="p">,</span> <span class="s1">&#39;loop&#39;</span><span class="p">,</span> <span class="s1">&#39;of&#39;</span><span class="p">,</span> <span class="s1">&#39;by&#39;</span><span class="p">,</span> <span class="s1">&#39;when&#39;</span><span class="p">]</span>
<span class="nx">COFFEE_KEYWORDS</span><span class="p">.</span><span class="nx">push</span> <span class="nx">op</span> <span class="k">for</span> <span class="nx">op</span> <span class="k">of</span> <span class="nv">COFFEE_ALIASES =</span>
<span class="nv">COFFEE_ALIAS_MAP =</span>
<span class="o">and</span> <span class="o">:</span> <span class="s1">&#39;&amp;&amp;&#39;</span>
<span class="o">or</span> <span class="o">:</span> <span class="s1">&#39;||&#39;</span>
<span class="o">is</span> <span class="o">:</span> <span class="s1">&#39;==&#39;</span>
@@ -403,7 +408,10 @@ token stream.</p> </td> <td class="code">
<span class="kc">yes</span> <span class="o">:</span> <span class="s1">&#39;true&#39;</span>
<span class="kc">no</span> <span class="o">:</span> <span class="s1">&#39;false&#39;</span>
<span class="kc">on</span> <span class="o">:</span> <span class="s1">&#39;true&#39;</span>
<span class="kc">off</span> <span class="o">:</span> <span class="s1">&#39;false&#39;</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>The list of keywords that are reserved by JavaScript, but not used, or are
<span class="kc">off</span> <span class="o">:</span> <span class="s1">&#39;false&#39;</span>
<span class="nv">COFFEE_ALIASES = </span><span class="p">(</span><span class="nx">key</span> <span class="k">for</span> <span class="nx">key</span> <span class="k">of</span> <span class="nx">COFFEE_ALIAS_MAP</span><span class="p">)</span>
<span class="nv">COFFEE_KEYWORDS = </span><span class="nx">COFFEE_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">COFFEE_ALIASES</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>The list of keywords that are reserved by JavaScript, but not used, or are
used by CoffeeScript internally. We throw an error when these are encountered,
to avoid having a JavaScript error at runtime.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">RESERVED = </span><span class="p">[</span>
<span class="s1">&#39;case&#39;</span><span class="p">,</span> <span class="s1">&#39;default&#39;</span><span class="p">,</span> <span class="s1">&#39;function&#39;</span><span class="p">,</span> <span class="s1">&#39;var&#39;</span><span class="p">,</span> <span class="s1">&#39;void&#39;</span><span class="p">,</span> <span class="s1">&#39;with&#39;</span>
@@ -445,7 +453,7 @@ be used as identifiers or properties.</p> </td> <td clas
<span class="nv">SIMPLESTR = </span><span class="sr">/^&#39;[^\\&#39;]*(?:\\.[^\\&#39;]*)*&#39;/</span>
<span class="nv">JSTOKEN = </span><span class="sr">/^`[^\\`]*(?:\\.[^\\`]*)*`/</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>Regex-matching-regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REGEX = </span><span class="err">/// ^</span>
<span class="o">/</span> <span class="p">(</span><span class="o">?!</span> <span class="err">\</span><span class="nx">s</span> <span class="p">)</span> <span class="c1"># disallow leading whitespace</span>
<span class="o">/</span> <span class="p">(</span><span class="o">?!</span> <span class="p">[</span><span class="err">\</span><span class="nx">s</span><span class="o">=</span><span class="p">]</span> <span class="p">)</span> <span class="c1"># disallow leading whitespace or equals signs</span>
<span class="p">[</span><span class="o">^</span> <span class="p">[</span> <span class="err">/ \n \\ ]* # every other thing</span>
<span class="p">(</span><span class="o">?:</span>
<span class="p">(</span><span class="o">?:</span> <span class="err">\\</span><span class="p">[</span><span class="err">\</span><span class="nx">s</span><span class="err">\</span><span class="nx">S</span><span class="p">]</span> <span class="c1"># anything escaped</span>
@@ -464,9 +472,11 @@ be used as identifiers or properties.</p> </td> <td clas
<span class="nv">HEREDOC_INDENT = </span><span class="sr">/\n+([^\n\S]*)/g</span>
<span class="nv">HEREDOC_ILLEGAL = </span><span class="sr">/\*\//</span>
<span class="nv">ASSIGNED = </span><span class="sr">/^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|[&#39;&quot;].*[&#39;&quot;])[^\n\S]*?[:=][^:=&gt;]/</span>
<span class="nv">LINE_CONTINUER = </span><span class="err">/// ^ \s* (?: , | \??\.(?!\.) | :: ) ///</span>
<span class="nv">LINE_CONTINUER = </span><span class="err">/// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///</span>
<span class="nv">TRAILING_SPACES = </span><span class="sr">/\s+$/</span>

View File

@@ -29,7 +29,7 @@ return results).</p> </td> <td class="code">
<span class="k">else</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">compileClosure</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Statements converted into expressions via closure-wrapping share a scope
object with their parent closure, to preserve the expected lexical scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileClosure</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@jumps</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">@jumps</span><span class="p">()</span> <span class="o">or</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">Throw</span>
<span class="k">throw</span> <span class="nx">SyntaxError</span> <span class="s1">&#39;cannot use a pure statement in an expression.&#39;</span>
<span class="nv">o.sharedScope = </span><span class="kc">yes</span>
<span class="nx">Closure</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">compileNode</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>If the code generation wishes to use the result of a complex expression
@@ -152,7 +152,6 @@ clean up obvious double-parentheses.</p> </td> <td class
<span class="nv">o.scope = </span><span class="k">new</span> <span class="nx">Scope</span> <span class="kc">null</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="kc">null</span>
<span class="nv">o.level = </span><span class="nx">LEVEL_TOP</span>
<span class="nv">code = </span><span class="nx">@compileWithDeclarations</span> <span class="nx">o</span>
<span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">TRAILING_WHITESPACE</span><span class="p">,</span> <span class="s1">&#39;&#39;</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(function() {\n#{code}\n}).call(this);\n&quot;</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Compile the expressions body for the contents of a function, with
declarations of all inner variables pushed up to the top.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileWithDeclarations</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">code = post = </span><span class="s1">&#39;&#39;</span>
@@ -167,7 +166,7 @@ declarations of all inner variables pushed up to the top.</p> </td>
<span class="nv">post = </span><span class="nx">@compileNode</span> <span class="nx">o</span>
<span class="p">{</span><span class="nx">scope</span><span class="p">}</span> <span class="o">=</span> <span class="nx">o</span>
<span class="k">if</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">expressions</span> <span class="o">is</span> <span class="k">this</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">hasDeclarations</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">hasDeclarations</span><span class="p">()</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">&quot;#{@tab}var #{ scope.declaredVariables().join(&#39;, &#39;) };\n&quot;</span>
<span class="k">if</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">hasAssignments</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">&quot;#{@tab}var #{ multident scope.assignedVariables().join(&#39;, &#39;), @tab };\n&quot;</span>
@@ -285,19 +284,22 @@ evaluate anything twice when building the soak chain.</p> </td>
<span class="nv">code = </span><span class="s2">&quot;(#{code})&quot;</span> <span class="k">if</span> <span class="nx">props</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">Access</span> <span class="o">and</span> <span class="nx">@isSimpleNumber</span><span class="p">()</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">props</span>
<span class="nx">code</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>Unfold a soak into an <code>If</code>: <code>a?.b</code> -> <code>a.b if a?</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unfoldSoak</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nv">ifn = </span><span class="nx">@base</span><span class="p">.</span><span class="nx">unfoldSoak</span> <span class="nx">o</span>
<span class="nb">Array</span><span class="o">::</span><span class="nx">push</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">ifn</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">properties</span><span class="p">,</span> <span class="nx">@properties</span>
<span class="k">return</span> <span class="nx">ifn</span>
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">soak</span>
<span class="nv">prop.soak = </span><span class="kc">off</span>
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">i</span>
<span class="nv">snd = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">i</span>
<span class="k">if</span> <span class="nx">fst</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;ref&#39;</span>
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">fst</span>
<span class="nv">snd.base = </span><span class="nx">ref</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">If</span> <span class="k">new</span> <span class="nx">Existence</span><span class="p">(</span><span class="nx">fst</span><span class="p">),</span> <span class="nx">snd</span><span class="p">,</span> <span class="nx">soak</span><span class="o">:</span> <span class="kc">on</span>
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <h3>Comment</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">&#182;</a> </div> <p>CoffeeScript passes through block comments as JavaScript block comments
<span class="k">return</span> <span class="nx">@unfoldedSoak</span> <span class="k">if</span> <span class="nx">@unfoldedSoak</span><span class="o">?</span>
<span class="nv">result = </span><span class="nx">do</span> <span class="o">=&gt;</span>
<span class="k">if</span> <span class="nv">ifn = </span><span class="nx">@base</span><span class="p">.</span><span class="nx">unfoldSoak</span> <span class="nx">o</span>
<span class="nb">Array</span><span class="o">::</span><span class="nx">push</span><span class="p">.</span><span class="nx">apply</span> <span class="nx">ifn</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">properties</span><span class="p">,</span> <span class="nx">@properties</span>
<span class="k">return</span> <span class="nx">ifn</span>
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">soak</span>
<span class="nv">prop.soak = </span><span class="kc">off</span>
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">i</span>
<span class="nv">snd = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">i</span>
<span class="k">if</span> <span class="nx">fst</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;ref&#39;</span>
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">fst</span>
<span class="nv">snd.base = </span><span class="nx">ref</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">If</span> <span class="k">new</span> <span class="nx">Existence</span><span class="p">(</span><span class="nx">fst</span><span class="p">),</span> <span class="nx">snd</span><span class="p">,</span> <span class="nx">soak</span><span class="o">:</span> <span class="kc">on</span>
<span class="kc">null</span>
<span class="vi">@unfoldedSoak = </span><span class="nx">result</span> <span class="o">or</span> <span class="kc">no</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <h3>Comment</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">&#182;</a> </div> <p>CoffeeScript passes through block comments as JavaScript block comments
at the same position.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Comment = </span><span class="nx">class</span> <span class="nx">Comment</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@comment</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -339,7 +341,7 @@ method.</p> </td> <td class="code"> <div c
<span class="nv">rite = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">left</span>
<span class="nv">rite = </span><span class="k">new</span> <span class="nx">Call</span> <span class="nx">rite</span><span class="p">,</span> <span class="nx">@args</span>
<span class="nv">rite.isNew = </span><span class="nx">@isNew</span>
<span class="nv">left = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;typeof #{ left.compile o } == \&quot;function\&quot;&quot;</span>
<span class="nv">left = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;typeof #{ left.compile o } === \&quot;function\&quot;&quot;</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">left</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">rite</span><span class="p">),</span> <span class="nx">soak</span><span class="o">:</span> <span class="kc">yes</span>
<span class="nv">call = </span><span class="k">this</span>
<span class="nv">list = </span><span class="p">[]</span>
@@ -358,17 +360,33 @@ method.</p> </td> <td class="code"> <div c
<span class="k">else</span>
<span class="nv">call.variable.base = </span><span class="nx">ifn</span>
<span class="nv">ifn = </span><span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">call</span><span class="p">,</span> <span class="s1">&#39;variable&#39;</span>
<span class="nx">ifn</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">&#182;</a> </div> <p>Compile a vanilla function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">ifn</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">&#182;</a> </div> <p>Walk through the objects in the arguments, moving over simple values.
This allows syntax like <code>call a: b, c</code> into <code>call({a: b}, c);</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">filterImplicitObjects</span><span class="o">:</span> <span class="p">(</span><span class="nx">list</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">nodes = </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">list</span>
<span class="nx">unless</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isObject</span><span class="o">?</span><span class="p">()</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">generated</span>
<span class="nx">nodes</span><span class="p">.</span><span class="nx">push</span> <span class="nx">node</span>
<span class="k">continue</span>
<span class="nv">obj = </span><span class="kc">null</span>
<span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">node</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span>
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
<span class="nx">nodes</span><span class="p">.</span><span class="nx">push</span> <span class="nv">obj = </span><span class="k">new</span> <span class="nx">Obj</span> <span class="nv">properties = </span><span class="p">[],</span> <span class="kc">true</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">obj</span>
<span class="nx">properties</span><span class="p">.</span><span class="nx">push</span> <span class="nx">prop</span>
<span class="k">else</span>
<span class="nx">nodes</span><span class="p">.</span><span class="nx">push</span> <span class="nx">prop</span>
<span class="nv">obj = </span><span class="kc">null</span>
<span class="nx">nodes</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>Compile a vanilla function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@variable</span><span class="o">?</span><span class="p">.</span><span class="nv">front = </span><span class="nx">@front</span>
<span class="k">if</span> <span class="nv">code = </span><span class="nx">Splat</span><span class="p">.</span><span class="nx">compileSplattedArray</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">@args</span><span class="p">,</span> <span class="kc">true</span>
<span class="k">return</span> <span class="nx">@compileSplat</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">code</span>
<span class="nv">args = </span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">@args</span><span class="p">).</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="nv">args = </span><span class="nx">@filterImplicitObjects</span> <span class="nx">@args</span>
<span class="nv">args = </span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">args</span><span class="p">).</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="k">if</span> <span class="nx">@isSuper</span>
<span class="nx">@superReference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;.call(this#{ args and &#39;, &#39; + args })&quot;</span>
<span class="k">else</span>
<span class="p">(</span><span class="k">if</span> <span class="nx">@isNew</span> <span class="k">then</span> <span class="s1">&#39;new &#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;(#{args})&quot;</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p><code>super()</code> is converted into a call against the superclass's implementation
<span class="p">(</span><span class="k">if</span> <span class="nx">@isNew</span> <span class="k">then</span> <span class="s1">&#39;new &#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;(#{args})&quot;</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p><code>super()</code> is converted into a call against the superclass's implementation
of the current function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSuper</span><span class="o">:</span> <span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;#{@superReference(o)}.call(this#{ if args.length then &#39;, &#39; else &#39;&#39; }#{args})&quot;</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>If you call a function with a splat, it's converted into a JavaScript
<span class="s2">&quot;#{@superReference(o)}.call(this#{ if args.length then &#39;, &#39; else &#39;&#39; }#{args})&quot;</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">&#182;</a> </div> <p>If you call a function with a splat, it's converted into a JavaScript
<code>.apply()</code> call to allow an array of arguments to be passed.
If it's a constructor, then things get real tricky. We have to inject an
inner constructor in order to be able to pass the varargs.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplat</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">splatArgs</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -376,11 +394,11 @@ inner constructor in order to be able to pass the varargs.</p> </td>
<span class="k">if</span> <span class="nx">@isNew</span>
<span class="nv">idt = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
<span class="k">return</span> <span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> (function(func, args, ctor) {</span>
<span class="s2"> #{idt}ctor.prototype = func.prototype;</span>
<span class="s2"> #{idt}var child = new ctor, result = func.apply(child, args);</span>
<span class="s2"> #{idt}return typeof result == &quot;</span><span class="nx">object</span><span class="s2">&quot; ? result : child;</span>
<span class="s2"> #{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})</span>
<span class="s2"> (function(func, args, ctor) {</span>
<span class="s2"> #{idt}ctor.prototype = func.prototype;</span>
<span class="s2"> #{idt}var child = new ctor, result = func.apply(child, args);</span>
<span class="s2"> #{idt}return typeof result === &quot;</span><span class="nx">object</span><span class="s2">&quot; ? result : child;</span>
<span class="s2"> #{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})</span>
<span class="s2"> &quot;&quot;&quot;</span>
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@variable</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">name = </span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">())</span> <span class="o">and</span> <span class="nx">base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
@@ -394,14 +412,14 @@ inner constructor in order to be able to pass the varargs.</p> </td>
<span class="nx">fun</span> <span class="o">+=</span> <span class="nx">name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="k">else</span>
<span class="nv">ref = </span><span class="s1">&#39;null&#39;</span>
<span class="s2">&quot;#{fun}.apply(#{ref}, #{splatArgs})&quot;</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">&#182;</a> </div> <h3>Extends</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">&#182;</a> </div> <p>Node to extend an object's prototype with an ancestor object.
<span class="s2">&quot;#{fun}.apply(#{ref}, #{splatArgs})&quot;</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">&#182;</a> </div> <h3>Extends</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>Node to extend an object's prototype with an ancestor object.
After <code>goog.inherits</code> from the
<a href="http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.html">Closure Library</a>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Extends = </span><span class="nx">class</span> <span class="nx">Extends</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@child</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;child&#39;</span><span class="p">,</span> <span class="s1">&#39;parent&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>Hooks one constructor into another's prototype chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compile</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;child&#39;</span><span class="p">,</span> <span class="s1">&#39;parent&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">&#182;</a> </div> <p>Hooks one constructor into another's prototype chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compile</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">utility</span> <span class="s1">&#39;hasProp&#39;</span>
<span class="k">new</span> <span class="nx">Call</span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">utility</span> <span class="s1">&#39;extends&#39;</span><span class="p">),</span> <span class="p">[</span><span class="nx">@child</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">]).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">&#182;</a> </div> <h3>Access</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">&#182;</a> </div> <p>A <code>.</code> access into a property of a value, or the <code>::</code> shorthand for
<span class="k">new</span> <span class="nx">Call</span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">utility</span> <span class="s1">&#39;extends&#39;</span><span class="p">),</span> <span class="p">[</span><span class="nx">@child</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">]).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">&#182;</a> </div> <h3>Access</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">&#182;</a> </div> <p>A <code>.</code> access into a property of a value, or the <code>::</code> shorthand for
an access into the object's prototype.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Access = </span><span class="nx">class</span> <span class="nx">Access</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@name</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@name.asKey = </span><span class="kc">yes</span>
@@ -414,7 +432,7 @@ an access into the object's prototype.</p> </td> <td cla
<span class="nv">name = </span><span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nx">@proto</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">IS_STRING</span><span class="p">.</span><span class="nx">test</span> <span class="nx">name</span> <span class="k">then</span> <span class="s2">&quot;[#{name}]&quot;</span> <span class="k">else</span> <span class="s2">&quot;.#{name}&quot;</span>
<span class="nx">isComplex</span><span class="o">:</span> <span class="nx">NO</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">&#182;</a> </div> <h3>Index</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">&#182;</a> </div> <p>A <code>[ ... ]</code> indexed access into an array or object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Index = </span><span class="nx">class</span> <span class="nx">Index</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">isComplex</span><span class="o">:</span> <span class="nx">NO</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">&#182;</a> </div> <h3>Index</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">&#182;</a> </div> <p>A <code>[ ... ]</code> indexed access into an array or object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Index = </span><span class="nx">class</span> <span class="nx">Index</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@index</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;index&#39;</span><span class="p">]</span>
@@ -423,7 +441,7 @@ an access into the object's prototype.</p> </td> <td cla
<span class="p">(</span><span class="k">if</span> <span class="nx">@proto</span> <span class="k">then</span> <span class="s1">&#39;.prototype&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;[#{ @index.compile o, LEVEL_PAREN }]&quot;</span>
<span class="nx">isComplex</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@index</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">&#182;</a> </div> <h3>Range</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">&#182;</a> </div> <p>A range literal. Ranges can be used to extract portions (slices) of arrays,
<span class="nx">@index</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">&#182;</a> </div> <h3>Range</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">&#182;</a> </div> <p>A range literal. Ranges can be used to extract portions (slices) of arrays,
to specify a range for comprehensions, or as a value, to be expanded into the
corresponding array of integers at runtime.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Range = </span><span class="nx">class</span> <span class="nx">Range</span> <span class="k">extends</span> <span class="nx">Base</span>
@@ -431,7 +449,7 @@ corresponding array of integers at runtime.</p> </td> <t
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@from</span><span class="p">,</span> <span class="nx">@to</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@exclusive = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;exclusive&#39;</span>
<span class="vi">@equals = </span><span class="k">if</span> <span class="nx">@exclusive</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="s1">&#39;=&#39;</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">&#182;</a> </div> <p>Compiles the range's source variables -- where it starts and where it ends.
<span class="vi">@equals = </span><span class="k">if</span> <span class="nx">@exclusive</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="s1">&#39;=&#39;</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">&#182;</a> </div> <p>Compiles the range's source variables -- where it starts and where it ends.
But only if they need to be cached to avoid double evaluation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileVariables</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o = </span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">top</span><span class="o">:</span> <span class="kc">true</span><span class="p">)</span>
<span class="p">[</span><span class="nx">@from</span><span class="p">,</span> <span class="nx">@fromVar</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@from</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
@@ -439,27 +457,29 @@ But only if they need to be cached to avoid double evaluation.</p> <
<span class="p">[</span><span class="nx">@fromNum</span><span class="p">,</span> <span class="nx">@toNum</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@fromVar</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLENUM</span><span class="p">),</span> <span class="nx">@toVar</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLENUM</span><span class="p">)]</span>
<span class="nv">parts = </span><span class="p">[]</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@from</span> <span class="k">if</span> <span class="nx">@from</span> <span class="o">isnt</span> <span class="nx">@fromVar</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@to</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">&#182;</a> </div> <p>When compiled normally, the range returns the contents of the <em>for loop</em>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@to</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p>When compiled normally, the range returns the contents of the <em>for loop</em>
needed to iterate over the values in the range. Used by comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@compileVariables</span> <span class="nx">o</span>
<span class="k">return</span> <span class="nx">@compileArray</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">index</span>
<span class="k">return</span> <span class="nx">@compileSimple</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span>
<span class="k">return</span> <span class="nx">@compileArray</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">index</span>
<span class="k">return</span> <span class="nx">@compileSimple</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span>
<span class="nv">idx = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;index&#39;</span>
<span class="nv">step = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;step&#39;</span>
<span class="nv">vars = </span><span class="s2">&quot;#{idx} = #{@from}&quot;</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span> <span class="k">then</span> <span class="s2">&quot;, #{@to}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">intro = </span><span class="s2">&quot;(#{@fromVar} &lt;= #{@toVar} ? #{idx}&quot;</span>
<span class="nv">compare = </span><span class="s2">&quot;#{intro} &lt;#{@equals} #{@toVar} : #{idx} &gt;#{@equals} #{@toVar})&quot;</span>
<span class="nv">stepPart = </span><span class="k">if</span> <span class="nx">step</span> <span class="k">then</span> <span class="nx">step</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;1&#39;</span>
<span class="nv">incr = </span><span class="k">if</span> <span class="nx">step</span> <span class="k">then</span> <span class="s2">&quot;#{idx} += #{stepPart}&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{intro} += #{stepPart} : #{idx} -= #{stepPart})&quot;</span>
<span class="s2">&quot;#{vars}; #{compare}; #{incr}&quot;</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p>Compile a simple range comprehension, with integers.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSimple</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">stepvar = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s2">&quot;step&quot;</span> <span class="k">if</span> <span class="nx">step</span>
<span class="nv">varPart = </span><span class="s2">&quot;#{idx} = #{@from}&quot;</span> <span class="o">+</span> <span class="p">(</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span> <span class="k">then</span> <span class="s2">&quot;, #{@to}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="p">)</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">step</span> <span class="k">then</span> <span class="s2">&quot;, #{stepvar} = #{step.compile(o)}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">cond = </span><span class="s2">&quot;#{@fromVar} &lt;= #{@toVar}&quot;</span>
<span class="nv">condPart = </span><span class="s2">&quot;#{cond} ? #{idx} &lt;#{@equals} #{@toVar} : #{idx} &gt;#{@equals} #{@toVar}&quot;</span>
<span class="nv">stepPart = </span><span class="k">if</span> <span class="nx">step</span> <span class="k">then</span> <span class="s2">&quot;#{idx} += #{stepvar}&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{cond} ? #{idx}++ : #{idx}--&quot;</span>
<span class="s2">&quot;#{varPart}; #{condPart}; #{stepPart}&quot;</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">&#182;</a> </div> <p>Compile a simple range comprehension, with integers.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSimple</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="o">+</span><span class="nx">@fromNum</span><span class="p">,</span> <span class="o">+</span><span class="nx">@toNum</span><span class="p">]</span>
<span class="nv">idx = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;index&#39;</span>
<span class="nv">step = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;step&#39;</span>
<span class="nx">step</span> <span class="o">and=</span> <span class="s2">&quot;#{idx} += #{step.compile(o)}&quot;</span>
<span class="k">if</span> <span class="nx">from</span> <span class="o">&lt;=</span> <span class="nx">to</span>
<span class="s2">&quot;#{idx} = #{from}; #{idx} &lt;#{@equals} #{to}; #{step or &quot;</span><span class="c1">#{idx}++&quot;}&quot;</span>
<span class="k">else</span>
<span class="s2">&quot;#{idx} = #{from}; #{idx} &gt;#{@equals} #{to}; #{step or &quot;</span><span class="c1">#{idx}--&quot;}&quot;</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">&#182;</a> </div> <p>When used as a value, expand the range into the equivalent array.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileArray</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">stepvar = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s2">&quot;step&quot;</span> <span class="k">if</span> <span class="nx">step</span>
<span class="nv">varPart = </span><span class="s2">&quot;#{idx} = #{from}&quot;</span>
<span class="nx">varPart</span> <span class="o">+=</span> <span class="s2">&quot;, #{stepvar} = #{step.compile(o)}&quot;</span> <span class="k">if</span> <span class="nx">step</span>
<span class="nv">condPart = </span><span class="k">if</span> <span class="nx">from</span> <span class="o">&lt;=</span> <span class="nx">to</span> <span class="k">then</span> <span class="s2">&quot;#{idx} &lt;#{@equals} #{to}&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{idx} &gt;#{@equals} #{to}&quot;</span>
<span class="nv">stepPart = </span><span class="s2">&quot;#{idx} += #{stepvar}&quot;</span> <span class="k">if</span> <span class="nx">step</span>
<span class="nv">stepPart = </span><span class="p">(</span> <span class="k">if</span> <span class="nx">from</span> <span class="o">&lt;=</span> <span class="nx">to</span> <span class="k">then</span> <span class="s2">&quot;#{idx}++&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{idx}--&quot;</span> <span class="p">)</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">step</span>
<span class="s2">&quot;#{varPart}; #{condPart}; #{stepPart}&quot;</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">&#182;</a> </div> <p>When used as a value, expand the range into the equivalent array.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileArray</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span> <span class="o">and</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="nx">@fromNum</span> <span class="o">-</span> <span class="nx">@toNum</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">20</span>
<span class="nv">range = </span><span class="p">[</span><span class="o">+</span><span class="nx">@fromNum</span><span class="p">..</span><span class="o">+</span><span class="nx">@toNum</span><span class="p">]</span>
<span class="nx">range</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@exclusive</span>
@@ -470,20 +490,20 @@ needed to iterate over the values in the range. Used by comprehensions.</p>
<span class="nv">pre = </span><span class="s2">&quot;\n#{idt}#{result} = [];&quot;</span>
<span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span>
<span class="nv">o.index = </span><span class="nx">i</span>
<span class="nv">body = </span><span class="nx">@compileSimple</span> <span class="nx">o</span>
<span class="nv">body = </span><span class="nx">@compileSimple</span> <span class="nx">o</span>
<span class="k">else</span>
<span class="nv">vars = </span><span class="s2">&quot;#{i} = #{@from}&quot;</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span> <span class="k">then</span> <span class="s2">&quot;, #{@to}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">clause = </span><span class="s2">&quot;#{@fromVar} &lt;= #{@toVar} ?&quot;</span>
<span class="nv">body = </span><span class="s2">&quot;var #{vars}; #{clause} #{i} &lt;#{@equals} #{@toVar} : #{i} &gt;#{@equals} #{@toVar}; #{clause} #{i} += 1 : #{i} -= 1&quot;</span>
<span class="nv">vars = </span><span class="s2">&quot;#{i} = #{@from}&quot;</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span> <span class="k">then</span> <span class="s2">&quot;, #{@to}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">cond = </span><span class="s2">&quot;#{@fromVar} &lt;= #{@toVar}&quot;</span>
<span class="nv">body = </span><span class="s2">&quot;var #{vars}; #{cond} ? #{i} &lt;#{@equals} #{@toVar} : #{i} &gt;#{@equals} #{@toVar}; #{cond} ? #{i}++ : #{i}--&quot;</span>
<span class="nv">post = </span><span class="s2">&quot;{ #{result}.push(#{i}); }\n#{idt}return #{result};\n#{o.indent}&quot;</span>
<span class="s2">&quot;(function() {#{pre}\n#{idt}for (#{body})#{post}}).apply(this, arguments)&quot;</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">&#182;</a> </div> <h3>Slice</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">&#182;</a> </div> <p>An array slice literal. Unlike JavaScript's <code>Array#slice</code>, the second parameter
<span class="s2">&quot;(function() {#{pre}\n#{idt}for (#{body})#{post}}).apply(this, arguments)&quot;</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">&#182;</a> </div> <h3>Slice</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-68">&#182;</a> </div> <p>An array slice literal. Unlike JavaScript's <code>Array#slice</code>, the second parameter
specifies the index of the end of the slice, just as the first parameter
is the index of the beginning.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Slice = </span><span class="nx">class</span> <span class="nx">Slice</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;range&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@range</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-68">&#182;</a> </div> <p>We have to be careful when trying to slice through the end of the array,
<span class="k">super</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-69">&#182;</a> </div> <p>We have to be careful when trying to slice through the end of the array,
<code>9e9</code> is used because not all implementations respect <code>undefined</code> or <code>1/0</code>.
<code>9e9</code> should be safe because <code>9e9</code> > <code>2**32</code>, the max array length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">{</span><span class="nx">to</span><span class="p">,</span> <span class="nx">from</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@range</span>
@@ -496,7 +516,7 @@ is the index of the beginning.</p> </td> <td class="code
<span class="p">(</span><span class="o">+</span><span class="nx">compiled</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
<span class="k">else</span>
<span class="s2">&quot;(#{compiled} + 1) || 9e9&quot;</span>
<span class="s2">&quot;.slice(#{ fromStr }#{ toStr or &#39;&#39; })&quot;</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-69">&#182;</a> </div> <h3>Obj</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-70">&#182;</a> </div> <p>An object literal, nothing fancy.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Obj = </span><span class="nx">class</span> <span class="nx">Obj</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="s2">&quot;.slice(#{ fromStr }#{ toStr or &#39;&#39; })&quot;</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-70">&#182;</a> </div> <h3>Obj</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-71">&#182;</a> </div> <p>An object literal, nothing fancy.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Obj = </span><span class="nx">class</span> <span class="nx">Obj</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">props</span><span class="p">,</span> <span class="vi">@generated = </span><span class="kc">false</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@objects = @properties = </span><span class="nx">props</span> <span class="o">or</span> <span class="p">[]</span>
@@ -505,6 +525,9 @@ is the index of the beginning.</p> </td> <td class="code
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">props = </span><span class="nx">@properties</span>
<span class="k">return</span> <span class="p">(</span><span class="k">if</span> <span class="nx">@front</span> <span class="k">then</span> <span class="s1">&#39;({})&#39;</span> <span class="k">else</span> <span class="s1">&#39;{}&#39;</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span>
<span class="k">if</span> <span class="nx">@generated</span>
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">props</span> <span class="k">when</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Value</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s1">&#39;cannot have an implicit value in an implicit object&#39;</span>
<span class="nv">idt = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
<span class="nv">lastNoncom = </span><span class="nx">@lastNonComment</span> <span class="nx">@properties</span>
<span class="nv">props = </span><span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">props</span>
@@ -528,17 +551,20 @@ is the index of the beginning.</p> </td> <td class="code
<span class="nx">assigns</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span> <span class="k">then</span> <span class="k">return</span> <span class="kc">yes</span>
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-71">&#182;</a> </div> <h3>Arr</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-72">&#182;</a> </div> <p>An array literal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Arr = </span><span class="nx">class</span> <span class="nx">Arr</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-72">&#182;</a> </div> <h3>Arr</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-73">&#182;</a> </div> <p>An array literal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Arr = </span><span class="nx">class</span> <span class="nx">Arr</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">objs</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@objects = </span><span class="nx">objs</span> <span class="o">or</span> <span class="p">[]</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;objects&#39;</span><span class="p">]</span>
<span class="nx">filterImplicitObjects</span><span class="o">:</span> <span class="nx">Call</span><span class="o">::</span><span class="nx">filterImplicitObjects</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="s1">&#39;[]&#39;</span> <span class="nx">unless</span> <span class="nx">@objects</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
<span class="k">return</span> <span class="nx">code</span> <span class="k">if</span> <span class="nv">code = </span><span class="nx">Splat</span><span class="p">.</span><span class="nx">compileSplattedArray</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">@objects</span>
<span class="nv">code = </span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">@objects</span><span class="p">).</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="nv">objs = </span><span class="nx">@filterImplicitObjects</span> <span class="nx">@objects</span>
<span class="k">return</span> <span class="nx">code</span> <span class="k">if</span> <span class="nv">code = </span><span class="nx">Splat</span><span class="p">.</span><span class="nx">compileSplattedArray</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">objs</span>
<span class="nv">code = </span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">objs</span><span class="p">).</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="k">if</span> <span class="nx">code</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;\n&#39;</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span>
<span class="s2">&quot;[\n#{o.indent}#{code}\n#{@tab}]&quot;</span>
<span class="k">else</span>
@@ -546,20 +572,20 @@ is the index of the beginning.</p> </td> <td class="code
<span class="nx">assigns</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">@objects</span> <span class="k">when</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span> <span class="k">then</span> <span class="k">return</span> <span class="kc">yes</span>
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-73">&#182;</a> </div> <h3>Class</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-74">&#182;</a> </div> <p>The CoffeeScript class definition.
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-74">&#182;</a> </div> <h3>Class</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-75">&#182;</a> </div> <p>The CoffeeScript class definition.
Initialize a <strong>Class</strong> with its name, an optional superclass, and a
list of prototype property assignments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Class = </span><span class="nx">class</span> <span class="nx">Class</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">,</span> <span class="vi">@body = </span><span class="k">new</span> <span class="nx">Block</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@boundFuncs = </span><span class="p">[]</span>
<span class="vi">@body.classBody = </span><span class="kc">yes</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">,</span> <span class="s1">&#39;parent&#39;</span><span class="p">,</span> <span class="s1">&#39;body&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-75">&#182;</a> </div> <p>Figure out the appropriate name for the constructor function of this class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">determineName</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">,</span> <span class="s1">&#39;parent&#39;</span><span class="p">,</span> <span class="s1">&#39;body&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-76">&#182;</a> </div> <p>Figure out the appropriate name for the constructor function of this class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">determineName</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">null</span> <span class="nx">unless</span> <span class="nx">@variable</span>
<span class="nv">decl = </span><span class="k">if</span> <span class="nv">tail = </span><span class="nx">last</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</span>
<span class="nx">tail</span> <span class="k">instanceof</span> <span class="nx">Access</span> <span class="o">and</span> <span class="nx">tail</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">value</span>
<span class="k">else</span>
<span class="nx">@variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span>
<span class="nx">decl</span> <span class="o">and=</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">decl</span><span class="p">)</span> <span class="o">and</span> <span class="nx">decl</span></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-76">&#182;</a> </div> <p>For all <code>this</code>-references and bound functions in the class definition,
<span class="nx">decl</span> <span class="o">and=</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">decl</span><span class="p">)</span> <span class="o">and</span> <span class="nx">decl</span></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-77">&#182;</a> </div> <p>For all <code>this</code>-references and bound functions in the class definition,
<code>this</code> is the Class being constructed.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">setContext</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@body</span><span class="p">.</span><span class="nx">traverseChildren</span> <span class="kc">false</span><span class="p">,</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">classBody</span>
@@ -567,15 +593,15 @@ list of prototype property assignments.</p> </td> <td cl
<span class="nv">node.value = </span><span class="nx">name</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Code</span>
<span class="nv">node.klass = </span><span class="nx">name</span>
<span class="nv">node.context = </span><span class="nx">name</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">bound</span></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-77">&#182;</a> </div> <p>Ensure that all functions bound to the instance are proxied in the
<span class="nv">node.context = </span><span class="nx">name</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">bound</span></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-78">&#182;</a> </div> <p>Ensure that all functions bound to the instance are proxied in the
constructor.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addBoundFunctions</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@boundFuncs</span><span class="p">.</span><span class="nx">length</span>
<span class="k">for</span> <span class="nx">bvar</span> <span class="k">in</span> <span class="nx">@boundFuncs</span>
<span class="nv">bname = </span><span class="nx">bvar</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;this.#{bname} = #{utility &#39;bind&#39;}(this.#{bname}, this);&quot;</span></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-78">&#182;</a> </div> <p>Merge the properties from a top-level object as prototypal properties
on the class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addProperties</span><span class="o">:</span> <span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;this.#{bname} = #{utility &#39;bind&#39;}(this.#{bname}, this)&quot;</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-79">&#182;</a> </div> <p>Merge the properties from a top-level object as prototypal properties
on the class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addProperties</span><span class="o">:</span> <span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">props = </span><span class="nx">node</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span>
<span class="k">while</span> <span class="nv">assign = </span><span class="nx">props</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span>
<span class="nv">exprs = </span><span class="k">while</span> <span class="nv">assign = </span><span class="nx">props</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">assign</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
<span class="nv">base = </span><span class="nx">assign</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span>
<span class="k">delete</span> <span class="nx">assign</span><span class="p">.</span><span class="nx">context</span>
@@ -588,29 +614,32 @@ on the class.</p> </td> <td class="code">
<span class="k">if</span> <span class="nx">func</span> <span class="k">instanceof</span> <span class="nx">Code</span>
<span class="nv">assign = </span><span class="vi">@ctor = </span><span class="nx">func</span>
<span class="k">else</span>
<span class="nv">assign = </span><span class="vi">@ctor = </span><span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">name</span><span class="p">),</span> <span class="nx">func</span><span class="p">)</span>
<span class="vi">@externalCtor = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;class&#39;</span>
<span class="nv">assign = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">@externalCtor</span><span class="p">),</span> <span class="nx">func</span>
<span class="k">else</span>
<span class="nx">unless</span> <span class="nx">assign</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="k">this</span>
<span class="nv">assign.variable = </span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">base</span><span class="p">,</span> <span class="s1">&#39;proto&#39;</span><span class="p">)])</span>
<span class="k">if</span> <span class="nx">func</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">func</span><span class="p">.</span><span class="nx">bound</span>
<span class="nx">@boundFuncs</span><span class="p">.</span><span class="nx">push</span> <span class="nx">base</span>
<span class="nv">func.bound = </span><span class="kc">no</span>
<span class="nx">assign</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-79">&#182;</a> </div> <p>Walk the body of the class, looking for prototype properties to be converted.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">walkBody</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">assign</span>
<span class="nx">compact</span> <span class="nx">exprs</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-80">&#182;</a> </div> <p>Walk the body of the class, looking for prototype properties to be converted.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">walkBody</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@traverseChildren</span> <span class="kc">false</span><span class="p">,</span> <span class="p">(</span><span class="nx">child</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">child</span> <span class="k">instanceof</span> <span class="nx">Class</span>
<span class="k">if</span> <span class="nx">child</span> <span class="k">instanceof</span> <span class="nx">Block</span>
<span class="k">for</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nv">exps = </span><span class="nx">child</span><span class="p">.</span><span class="nx">expressions</span>
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isObject</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
<span class="nx">exps</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@addProperties</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">name</span>
<span class="nv">child.expressions = exps = </span><span class="nx">flatten</span> <span class="nx">exps</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-80">&#182;</a> </div> <p>Make sure that a constructor is defined for the class, and properly
<span class="nx">exps</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@addProperties</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">o</span>
<span class="nv">child.expressions = exps = </span><span class="nx">flatten</span> <span class="nx">exps</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-81">&#182;</a> </div> <p>Make sure that a constructor is defined for the class, and properly
configured.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ensureConstructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">@ctor</span>
<span class="vi">@ctor = </span><span class="k">new</span> <span class="nx">Code</span>
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Call</span> <span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Splat</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;arguments&#39;</span><span class="p">]</span> <span class="k">if</span> <span class="nx">@parent</span>
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;#{name}.__super__.constructor.apply(this, arguments)&quot;</span> <span class="k">if</span> <span class="nx">@parent</span>
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;#{@externalCtor}.apply(this, arguments)&quot;</span> <span class="k">if</span> <span class="nx">@externalCtor</span>
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@ctor</span>
<span class="vi">@ctor.ctor = @ctor.name = </span><span class="nx">name</span>
<span class="vi">@ctor.klass = </span><span class="kc">null</span>
<span class="vi">@ctor.noReturn = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-81">&#182;</a> </div> <p>Instead of generating the JavaScript string directly, we build up the
<span class="vi">@ctor.noReturn = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-82">&#182;</a> </div> <p>Instead of generating the JavaScript string directly, we build up the
equivalent syntax tree and compile that, in pieces. You can see the
constructor, property assignments, and inheritance getting built out below.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">decl = </span><span class="nx">@determineName</span><span class="p">()</span>
@@ -618,18 +647,19 @@ constructor, property assignments, and inheritance getting built out below.</p>
<span class="nv">lname = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">name</span>
<span class="nx">@setContext</span> <span class="nx">name</span>
<span class="nx">@walkBody</span> <span class="nx">name</span>
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">lname</span><span class="p">,</span> <span class="nx">@parent</span> <span class="k">if</span> <span class="nx">@parent</span>
<span class="nx">@walkBody</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">o</span>
<span class="nx">@ensureConstructor</span> <span class="nx">name</span>
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">lname</span><span class="p">,</span> <span class="nx">@parent</span> <span class="k">if</span> <span class="nx">@parent</span>
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@ctor</span> <span class="nx">unless</span> <span class="nx">@ctor</span> <span class="k">instanceof</span> <span class="nx">Code</span>
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">push</span> <span class="nx">lname</span>
<span class="nx">@addBoundFunctions</span> <span class="nx">o</span>
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">Closure</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">@body</span><span class="p">),</span> <span class="kc">true</span>
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="nx">@variable</span><span class="p">,</span> <span class="nx">klass</span> <span class="k">if</span> <span class="nx">@variable</span>
<span class="nx">klass</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-82">&#182;</a> </div> <h3>Assign</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-83"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-83">&#182;</a> </div> <p>The <strong>Assign</strong> is used to assign a local variable to value, or to set the
<span class="nx">klass</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-83"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-83">&#182;</a> </div> <h3>Assign</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-84"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-84">&#182;</a> </div> <p>The <strong>Assign</strong> is used to assign a local variable to value, or to set the
property of an object -- including within object literals.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Assign = </span><span class="nx">class</span> <span class="nx">Assign</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">,</span> <span class="nx">@value</span><span class="p">,</span> <span class="nx">@context</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@param = </span><span class="nx">options</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">param</span></pre></div> </td> </tr> <tr id="section-84"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-84">&#182;</a> </div> <p>Matchers for detecting class/method names</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">METHOD_DEF</span><span class="o">:</span> <span class="sr">/^(?:(\S+)\.prototype\.|\S+?)?\b([$A-Za-z_][$\w\x7f-\uffff]*)$/</span>
<span class="vi">@param = </span><span class="nx">options</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">param</span></pre></div> </td> </tr> <tr id="section-85"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-85">&#182;</a> </div> <p>Matchers for detecting class/method names</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">METHOD_DEF</span><span class="o">:</span> <span class="sr">/^(?:(\S+)\.prototype\.|\S+?)?\b([$A-Za-z_][$\w\x7f-\uffff]*)$/</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">,</span> <span class="s1">&#39;value&#39;</span><span class="p">]</span>
@@ -637,7 +667,7 @@ property of an object -- including within object literals.</p> </td>
<span class="err">@</span><span class="p">[</span><span class="k">if</span> <span class="nx">@context</span> <span class="o">is</span> <span class="s1">&#39;object&#39;</span> <span class="k">then</span> <span class="s1">&#39;value&#39;</span> <span class="k">else</span> <span class="s1">&#39;variable&#39;</span><span class="p">].</span><span class="nx">assigns</span> <span class="nx">name</span>
<span class="nx">unfoldSoak</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="s1">&#39;variable&#39;</span></pre></div> </td> </tr> <tr id="section-85"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-85">&#182;</a> </div> <p>Compile an assignment, delegating to <code>compilePatternMatch</code> or
<span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="s1">&#39;variable&#39;</span></pre></div> </td> </tr> <tr id="section-86"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-86">&#182;</a> </div> <p>Compile an assignment, delegating to <code>compilePatternMatch</code> or
<code>compileSplice</code> if appropriate. Keep track of the name of the base object
we've been assigned to, for correct internal references. If the variable
has not been seen yet within the current scope, declare it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -646,20 +676,20 @@ has not been seen yet within the current scope, declare it.</p> </td
<span class="k">return</span> <span class="nx">@compileSplice</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isSplice</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">@compileConditional</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@context</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;||=&#39;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;=&#39;</span><span class="p">,</span> <span class="s1">&#39;?=&#39;</span><span class="p">]</span>
<span class="nv">name = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="k">if</span> <span class="nx">@value</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nv">match = </span><span class="nx">@METHOD_DEF</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">name</span>
<span class="vi">@value.name = </span><span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="vi">@value.klass = </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nv">val = </span><span class="nx">@value</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="k">return</span> <span class="s2">&quot;#{name}: #{val}&quot;</span> <span class="k">if</span> <span class="nx">@context</span> <span class="o">is</span> <span class="s1">&#39;object&#39;</span>
<span class="nx">unless</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isAssignable</span><span class="p">()</span>
<span class="nx">unless</span> <span class="nx">@context</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isAssignable</span><span class="p">()</span>
<span class="k">throw</span> <span class="nx">SyntaxError</span> <span class="s2">&quot;\&quot;#{ @variable.compile o }\&quot; cannot be assigned.&quot;</span>
<span class="nx">unless</span> <span class="nx">@context</span> <span class="o">or</span> <span class="nx">isValue</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">namespaced</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">hasProperties</span><span class="p">())</span>
<span class="k">if</span> <span class="nx">@param</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">&#39;var&#39;</span>
<span class="k">else</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">find</span> <span class="nx">name</span>
<span class="k">if</span> <span class="nx">@value</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nv">match = </span><span class="nx">@METHOD_DEF</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">name</span>
<span class="vi">@value.name = </span><span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="vi">@value.klass = </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nv">val = </span><span class="nx">@value</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="k">return</span> <span class="s2">&quot;#{name}: #{val}&quot;</span> <span class="k">if</span> <span class="nx">@context</span> <span class="o">is</span> <span class="s1">&#39;object&#39;</span>
<span class="nv">val = </span><span class="nx">name</span> <span class="o">+</span> <span class="s2">&quot; #{ @context or &#39;=&#39; } &quot;</span> <span class="o">+</span> <span class="nx">val</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;=</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">val</span> <span class="k">else</span> <span class="s2">&quot;(#{val})&quot;</span></pre></div> </td> </tr> <tr id="section-86"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-86">&#182;</a> </div> <p>Brief implementation of recursive pattern matching, when assigning array or
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;=</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">val</span> <span class="k">else</span> <span class="s2">&quot;(#{val})&quot;</span></pre></div> </td> </tr> <tr id="section-87"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-87">&#182;</a> </div> <p>Brief implementation of recursive pattern matching, when assigning array or
object literals to a value. Peeks at their properties to assign inner names.
See the <a href="http://wiki.ecmascript.org/doku.php?id=harmony:destructuring">ECMAScript Harmony Wiki</a>
for details.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compilePatternMatch</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -667,11 +697,10 @@ for details.</p> </td> <td class="code"> <
<span class="p">{</span><span class="nx">value</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
<span class="p">{</span><span class="nx">objects</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">base</span>
<span class="nx">unless</span> <span class="nv">olen = </span><span class="nx">objects</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">top</span>
<span class="nv">code = </span><span class="nx">value</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&gt;=</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span>
<span class="nv">isObject = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">isObject</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">top</span> <span class="o">and</span> <span class="nx">olen</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="p">(</span><span class="nv">obj = </span><span class="nx">objects</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Splat</span></pre></div> </td> </tr> <tr id="section-87"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-87">&#182;</a> </div> <p>Unroll simplest cases: <code>{v} = x</code> -> <code>v = x.v</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
<span class="k">if</span> <span class="nx">top</span> <span class="o">and</span> <span class="nx">olen</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="p">(</span><span class="nv">obj = </span><span class="nx">objects</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Splat</span></pre></div> </td> </tr> <tr id="section-88"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-88">&#182;</a> </div> <p>Unroll simplest cases: <code>{v} = x</code> -> <code>v = x.v</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
<span class="p">{</span><span class="nx">variable</span><span class="o">:</span> <span class="p">{</span><span class="nx">base</span><span class="o">:</span> <span class="nx">idx</span><span class="p">},</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">obj</span><span class="p">}</span> <span class="o">=</span> <span class="nx">obj</span>
<span class="k">else</span>
<span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Parens</span>
@@ -691,10 +720,10 @@ for details.</p> </td> <td class="code"> <
<span class="k">if</span> <span class="o">not</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">vvar</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">assigns</span><span class="p">(</span><span class="nx">vvar</span><span class="p">)</span>
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span> <span class="s2">&quot;#{ ref = o.scope.freeVariable &#39;ref&#39; } = #{vvar}&quot;</span>
<span class="nv">vvar = </span><span class="nx">ref</span>
<span class="k">for</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">objects</span></pre></div> </td> </tr> <tr id="section-88"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-88">&#182;</a> </div> <p>A regular array pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idx = </span><span class="nx">i</span>
<span class="k">for</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">objects</span></pre></div> </td> </tr> <tr id="section-89"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-89">&#182;</a> </div> <p>A regular array pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idx = </span><span class="nx">i</span>
<span class="k">if</span> <span class="nx">isObject</span>
<span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span></pre></div> </td> </tr> <tr id="section-89"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-89">&#182;</a> </div> <p>A regular object pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">{</span><span class="nx">variable</span><span class="o">:</span> <span class="p">{</span><span class="nx">base</span><span class="o">:</span> <span class="nx">idx</span><span class="p">},</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">obj</span><span class="p">}</span> <span class="o">=</span> <span class="nx">obj</span>
<span class="k">else</span></pre></div> </td> </tr> <tr id="section-90"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-90">&#182;</a> </div> <p>A shorthand <code>{a, b, @c} = val</code> pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Parens</span>
<span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span></pre></div> </td> </tr> <tr id="section-90"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-90">&#182;</a> </div> <p>A regular object pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">{</span><span class="nx">variable</span><span class="o">:</span> <span class="p">{</span><span class="nx">base</span><span class="o">:</span> <span class="nx">idx</span><span class="p">},</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">obj</span><span class="p">}</span> <span class="o">=</span> <span class="nx">obj</span>
<span class="k">else</span></pre></div> </td> </tr> <tr id="section-91"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-91">&#182;</a> </div> <p>A shorthand <code>{a, b, @c} = val</code> pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Parens</span>
<span class="p">[</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()).</span><span class="nx">cacheReference</span> <span class="nx">o</span>
<span class="k">else</span>
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="k">this</span> <span class="k">then</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span> <span class="k">else</span> <span class="nx">obj</span>
@@ -720,12 +749,12 @@ for details.</p> </td> <td class="code"> <
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">vvar</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="p">(</span><span class="k">if</span> <span class="nx">acc</span> <span class="k">then</span> <span class="nx">Access</span> <span class="k">else</span> <span class="nx">Index</span><span class="p">)</span> <span class="nx">idx</span><span class="p">]</span>
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">val</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">param</span><span class="o">:</span> <span class="nx">@param</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span>
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span> <span class="nx">vvar</span> <span class="nx">unless</span> <span class="nx">top</span>
<span class="nv">code = </span><span class="p">(</span><span class="nx">compact</span> <span class="nx">assigns</span><span class="p">).</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-91"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-91">&#182;</a> </div> <p>When compiling a conditional assignment, take care to ensure that the
<span class="nv">code = </span><span class="nx">assigns</span><span class="p">.</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-92"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-92">&#182;</a> </div> <p>When compiling a conditional assignment, take care to ensure that the
operands are only evaluated once, even though we have to reference them
more than once.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileConditional</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">rite</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">cacheReference</span> <span class="nx">o</span>
<span class="k">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">@context</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="nx">left</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">rite</span><span class="p">,</span> <span class="nx">@value</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">)).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-92"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-92">&#182;</a> </div> <p>Compile the assignment from an array splice literal, using JavaScript's
<span class="k">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">@context</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="nx">left</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">rite</span><span class="p">,</span> <span class="nx">@value</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">)).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-93">&#182;</a> </div> <p>Compile the assignment from an array splice literal, using JavaScript's
<code>Array#splice</code> method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplice</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">{</span><span class="nx">range</span><span class="o">:</span> <span class="p">{</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">,</span> <span class="nx">exclusive</span><span class="p">}}</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nv">name = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
@@ -741,7 +770,7 @@ more than once.</p> </td> <td class="code">
<span class="nv">to = </span><span class="s2">&quot;9e9&quot;</span>
<span class="p">[</span><span class="nx">valDef</span><span class="p">,</span> <span class="nx">valRef</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nv">code = </span><span class="s2">&quot;[].splice.apply(#{name}, [#{fromDecl}, #{to}].concat(#{valDef})), #{valRef}&quot;</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&gt;</span> <span class="nx">LEVEL_TOP</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-93">&#182;</a> </div> <h3>Code</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-94"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-94">&#182;</a> </div> <p>A function definition. This is the only node that creates a new Scope.
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&gt;</span> <span class="nx">LEVEL_TOP</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-94"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-94">&#182;</a> </div> <h3>Code</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-95">&#182;</a> </div> <p>A function definition. This is the only node that creates a new Scope.
When for the purposes of walking the contents of a function body, the Code
has no <em>children</em> -- they're within the inner scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Code = </span><span class="nx">class</span> <span class="nx">Code</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">params</span><span class="p">,</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -754,7 +783,7 @@ has no <em>children</em> -- they're within the inner scope.</p> </td
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="o">!!</span><span class="nx">@ctor</span>
<span class="nx">jumps</span><span class="o">:</span> <span class="nx">NO</span></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-95">&#182;</a> </div> <p>Compilation creates a new scope unless explicitly asked to share with the
<span class="nx">jumps</span><span class="o">:</span> <span class="nx">NO</span></pre></div> </td> </tr> <tr id="section-96"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-96">&#182;</a> </div> <p>Compilation creates a new scope unless explicitly asked to share with the
outer scope. Handles splat parameters in the parameter list by peeking at
the JavaScript <code>arguments</code> objects. If the function is bound with the <code>=&gt;</code>
arrow, generates a wrapper that saves the current value of <code>this</code> through
@@ -763,10 +792,10 @@ a closure.</p> </td> <td class="code"> <di
<span class="nv">o.scope.shared = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;sharedScope&#39;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span>
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span>
<span class="nv">vars = </span><span class="p">[]</span>
<span class="nv">exprs = </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">param</span> <span class="k">in</span> <span class="nx">@params</span> <span class="k">when</span> <span class="nx">param</span><span class="p">.</span><span class="nx">splat</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">add</span> <span class="nx">param</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="s1">&#39;var&#39;</span> <span class="k">if</span> <span class="nx">param</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">value</span>
<span class="nv">splats = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Arr</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">asReference</span> <span class="nx">o</span> <span class="k">for</span> <span class="nx">p</span> <span class="k">in</span> <span class="nx">@params</span><span class="p">)),</span>
<span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;arguments&#39;</span>
<span class="k">break</span>
@@ -795,9 +824,9 @@ a closure.</p> </td> <td class="code"> <di
<span class="nx">code</span> <span class="o">+=</span> <span class="s1">&#39;}&#39;</span>
<span class="k">return</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="nx">code</span> <span class="k">if</span> <span class="nx">@ctor</span>
<span class="k">return</span> <span class="nx">utility</span><span class="p">(</span><span class="s1">&#39;bind&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;(#{code}, #{@context})&quot;</span> <span class="k">if</span> <span class="nx">@bound</span>
<span class="k">if</span> <span class="nx">@front</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&gt;=</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-96"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-96">&#182;</a> </div> <p>Short-circuit <code>traverseChildren</code> method to prevent it from crossing scope boundaries
<span class="k">if</span> <span class="nx">@front</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&gt;=</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-97"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-97">&#182;</a> </div> <p>Short-circuit <code>traverseChildren</code> method to prevent it from crossing scope boundaries
unless <code>crossScope</code> is <code>true</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">traverseChildren</span><span class="o">:</span> <span class="p">(</span><span class="nx">crossScope</span><span class="p">,</span> <span class="nx">func</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">(</span><span class="nx">crossScope</span><span class="p">,</span> <span class="nx">func</span><span class="p">)</span> <span class="k">if</span> <span class="nx">crossScope</span></pre></div> </td> </tr> <tr id="section-97"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-97">&#182;</a> </div> <h3>Param</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-98"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-98">&#182;</a> </div> <p>A parameter in a function definition. Beyond a typical Javascript parameter,
<span class="k">super</span><span class="p">(</span><span class="nx">crossScope</span><span class="p">,</span> <span class="nx">func</span><span class="p">)</span> <span class="k">if</span> <span class="nx">crossScope</span></pre></div> </td> </tr> <tr id="section-98"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-98">&#182;</a> </div> <h3>Param</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-99"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-99">&#182;</a> </div> <p>A parameter in a function definition. Beyond a typical Javascript parameter,
these parameters can also attach themselves to the context of the function,
as well as be a splat, gathering up a group of parameters into an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Param = </span><span class="nx">class</span> <span class="nx">Param</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@name</span><span class="p">,</span> <span class="nx">@value</span><span class="p">,</span> <span class="nx">@splat</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -820,7 +849,7 @@ as well as be a splat, gathering up a group of parameters into an array.</p>
<span class="vi">@reference = </span><span class="nx">node</span>
<span class="nx">isComplex</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@name</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-99"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-99">&#182;</a> </div> <h3>Splat</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-100"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-100">&#182;</a> </div> <p>A splat, either as a parameter to a function, an argument to a call,
<span class="nx">@name</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-100"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-100">&#182;</a> </div> <h3>Splat</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-101">&#182;</a> </div> <p>A splat, either as a parameter to a function, an argument to a call,
or as part of a destructuring assignment.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Splat = </span><span class="nx">class</span> <span class="nx">Splat</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span>
@@ -834,7 +863,7 @@ or as part of a destructuring assignment.</p> </td> <td
<span class="nx">@name</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span>
<span class="nx">compile</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@index</span><span class="o">?</span> <span class="k">then</span> <span class="nx">@compileParam</span> <span class="nx">o</span> <span class="k">else</span> <span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-101">&#182;</a> </div> <p>Utility function that converts arbitrary number of elements, mixed with
<span class="k">if</span> <span class="nx">@index</span><span class="o">?</span> <span class="k">then</span> <span class="nx">@compileParam</span> <span class="nx">o</span> <span class="k">else</span> <span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-102">&#182;</a> </div> <p>Utility function that converts arbitrary number of elements, mixed with
splats, to a proper array.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@compileSplattedArray</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">list</span><span class="p">,</span> <span class="nx">apply</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">index = </span><span class="o">-</span><span class="mi">1</span>
<span class="k">continue</span> <span class="k">while</span> <span class="p">(</span><span class="nv">node = </span><span class="nx">list</span><span class="p">[</span><span class="o">++</span><span class="nx">index</span><span class="p">])</span> <span class="o">and</span> <span class="nx">node</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
@@ -851,7 +880,7 @@ splats, to a proper array.</p> </td> <td class="code">
<span class="k">else</span> <span class="s2">&quot;[#{code}]&quot;</span>
<span class="k">return</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s2">&quot;.concat(#{ args.slice(1).join &#39;, &#39; })&quot;</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">is</span> <span class="mi">0</span>
<span class="nv">base = </span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">list</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span>
<span class="s2">&quot;[#{ base.join &#39;, &#39; }].concat(#{ args.join &#39;, &#39; })&quot;</span></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-102">&#182;</a> </div> <h3>While</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-103"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-103">&#182;</a> </div> <p>A while loop, the only sort of low-level loop exposed by CoffeeScript. From
<span class="s2">&quot;[#{ base.join &#39;, &#39; }].concat(#{ args.join &#39;, &#39; })&quot;</span></pre></div> </td> </tr> <tr id="section-103"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-103">&#182;</a> </div> <h3>While</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-104">&#182;</a> </div> <p>A while loop, the only sort of low-level loop exposed by CoffeeScript. From
it, all other loops can be manufactured. Useful in cases where you need more
flexibility or more speed than a comprehension can provide.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.While = </span><span class="nx">class</span> <span class="nx">While</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">condition</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -874,7 +903,7 @@ flexibility or more speed than a comprehension can provide.</p> </td
<span class="k">return</span> <span class="kc">no</span> <span class="nx">unless</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span>
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">expressions</span>
<span class="k">return</span> <span class="nx">node</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">jumps</span> <span class="nx">loop</span><span class="o">:</span> <span class="kc">yes</span>
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-104">&#182;</a> </div> <p>The main difference from a JavaScript <em>while</em> is that the CoffeeScript
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-105"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-105">&#182;</a> </div> <p>The main difference from a JavaScript <em>while</em> is that the CoffeeScript
<em>while</em> can be used as a part of a larger expression -- while loops may
return an array containing the computed result of each iteration.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
@@ -892,22 +921,25 @@ return an array containing the computed result of each iteration.</p>
<span class="nv">code = </span><span class="nx">set</span> <span class="o">+</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="s2">&quot;while (#{ @condition.compile o, LEVEL_PAREN }) {#{body}}&quot;</span>
<span class="k">if</span> <span class="nx">@returns</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">&quot;\n#{@tab}return #{rvar};&quot;</span>
<span class="nx">code</span></pre></div> </td> </tr> <tr id="section-105"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-105">&#182;</a> </div> <h3>Op</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-106"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-106">&#182;</a> </div> <p>Simple Arithmetic and logical operations. Performs some conversion from
<span class="nx">code</span></pre></div> </td> </tr> <tr id="section-106"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-106">&#182;</a> </div> <h3>Op</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-107"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-107">&#182;</a> </div> <p>Simple Arithmetic and logical operations. Performs some conversion from
CoffeeScript operations into their JavaScript equivalents.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Op = </span><span class="nx">class</span> <span class="nx">Op</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">op</span><span class="p">,</span> <span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">,</span> <span class="nx">flip</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">In</span> <span class="nx">first</span><span class="p">,</span> <span class="nx">second</span> <span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s1">&#39;in&#39;</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">first</span><span class="p">,</span> <span class="nx">first</span><span class="p">.</span><span class="nx">params</span> <span class="o">or</span> <span class="p">[]</span> <span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s1">&#39;do&#39;</span>
<span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s1">&#39;do&#39;</span>
<span class="nv">call = </span><span class="k">new</span> <span class="nx">Call</span> <span class="nx">first</span><span class="p">,</span> <span class="nx">first</span><span class="p">.</span><span class="nx">params</span> <span class="o">or</span> <span class="p">[]</span>
<span class="nv">call.do = </span><span class="kc">yes</span>
<span class="k">return</span> <span class="nx">call</span>
<span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s1">&#39;new&#39;</span>
<span class="k">return</span> <span class="nx">first</span><span class="p">.</span><span class="nx">newInstance</span><span class="p">()</span> <span class="k">if</span> <span class="nx">first</span> <span class="k">instanceof</span> <span class="nx">Call</span>
<span class="nv">first = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">first</span> <span class="k">if</span> <span class="nx">first</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">first</span><span class="p">.</span><span class="nx">bound</span>
<span class="k">return</span> <span class="nx">first</span><span class="p">.</span><span class="nx">newInstance</span><span class="p">()</span> <span class="k">if</span> <span class="nx">first</span> <span class="k">instanceof</span> <span class="nx">Call</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">first</span><span class="p">.</span><span class="nx">do</span>
<span class="nv">first = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">first</span> <span class="k">if</span> <span class="nx">first</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">first</span><span class="p">.</span><span class="nx">bound</span> <span class="o">or</span> <span class="nx">first</span><span class="p">.</span><span class="nx">do</span>
<span class="vi">@operator = </span><span class="nx">CONVERSIONS</span><span class="p">[</span><span class="nx">op</span><span class="p">]</span> <span class="o">or</span> <span class="nx">op</span>
<span class="vi">@first = </span><span class="nx">first</span>
<span class="vi">@second = </span><span class="nx">second</span>
<span class="vi">@flip = </span><span class="o">!!</span><span class="nx">flip</span>
<span class="k">return</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-107"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-107">&#182;</a> </div> <p>The map of conversions from CoffeeScript to JavaScript symbols.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">CONVERSIONS =</span>
<span class="k">return</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-108">&#182;</a> </div> <p>The map of conversions from CoffeeScript to JavaScript symbols.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">CONVERSIONS =</span>
<span class="s1">&#39;==&#39;</span><span class="o">:</span> <span class="s1">&#39;===&#39;</span>
<span class="s1">&#39;!=&#39;</span><span class="o">:</span> <span class="s1">&#39;!==&#39;</span>
<span class="s1">&#39;of&#39;</span><span class="o">:</span> <span class="s1">&#39;in&#39;</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-108">&#182;</a> </div> <p>The map of invertible operators.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">INVERSIONS =</span>
<span class="s1">&#39;of&#39;</span><span class="o">:</span> <span class="s1">&#39;in&#39;</span></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-109">&#182;</a> </div> <p>The map of invertible operators.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">INVERSIONS =</span>
<span class="s1">&#39;!==&#39;</span><span class="o">:</span> <span class="s1">&#39;===&#39;</span>
<span class="s1">&#39;===&#39;</span><span class="o">:</span> <span class="s1">&#39;!==&#39;</span>
@@ -916,7 +948,7 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="nx">isSimpleNumber</span><span class="o">:</span> <span class="nx">NO</span>
<span class="nx">isUnary</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="o">not</span> <span class="nx">@second</span></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-109">&#182;</a> </div> <p>Am I capable of
<span class="o">not</span> <span class="nx">@second</span></pre></div> </td> </tr> <tr id="section-110"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-110">&#182;</a> </div> <p>Am I capable of
<a href="http://docs.python.org/reference/expressions.html#notin">Python-style comparison chaining</a>?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">isChainable</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;===&#39;</span><span class="p">,</span> <span class="s1">&#39;!==&#39;</span><span class="p">]</span>
@@ -957,7 +989,7 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="vi">@first.front = </span><span class="nx">@front</span>
<span class="nv">code = </span><span class="nx">@first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="nx">@operator</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span>
<span class="nx">@second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;=</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-110"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-110">&#182;</a> </div> <p>Mimic Python's chained comparisons when multiple comparison operators are
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;=</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-111"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-111">&#182;</a> </div> <p>Mimic Python's chained comparisons when multiple comparison operators are
used sequentially. For example:</p>
<pre><code>bin/coffee -e 'console.log 50 &lt; 65 &gt; 10'
@@ -970,21 +1002,22 @@ true
<span class="nx">compileExistence</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
<span class="nv">ref = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;ref&#39;</span>
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">ref</span><span class="p">),</span> <span class="nx">@first</span>
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;ref&#39;</span>
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">@first</span>
<span class="k">else</span>
<span class="nv">fst = </span><span class="nx">@first</span>
<span class="nv">ref = </span><span class="nx">fst</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="k">new</span> <span class="nx">Existence</span><span class="p">(</span><span class="nx">fst</span><span class="p">).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot; ? #{ref} : #{ @second.compile o, LEVEL_LIST }&quot;</span></pre></div> </td> </tr> <tr id="section-111"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-111">&#182;</a> </div> <p>Compile a unary <strong>Op</strong>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileUnary</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">ref = </span><span class="nx">fst</span>
<span class="k">new</span> <span class="nx">If</span><span class="p">(</span><span class="k">new</span> <span class="nx">Existence</span><span class="p">(</span><span class="nx">fst</span><span class="p">),</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;if&#39;</span><span class="p">).</span><span class="nx">addElse</span><span class="p">(</span><span class="nx">@second</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-112"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-112">&#182;</a> </div> <p>Compile a unary <strong>Op</strong>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileUnary</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">parts = </span><span class="p">[</span><span class="nv">op = </span><span class="nx">@operator</span><span class="p">]</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="s1">&#39; &#39;</span> <span class="k">if</span> <span class="nx">op</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;new&#39;</span><span class="p">,</span> <span class="s1">&#39;typeof&#39;</span><span class="p">,</span> <span class="s1">&#39;delete&#39;</span><span class="p">]</span> <span class="o">or</span>
<span class="nx">op</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">Op</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">operator</span> <span class="o">is</span> <span class="nx">op</span>
<span class="vi">@first = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">@first</span> <span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s1">&#39;new&#39;</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isStatement</span> <span class="nx">o</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@flip</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">join</span> <span class="s1">&#39;&#39;</span>
<span class="nx">toString</span><span class="o">:</span> <span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span> <span class="nx">idt</span><span class="p">,</span> <span class="nx">@constructor</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="nx">@operator</span></pre></div> </td> </tr> <tr id="section-112"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-112">&#182;</a> </div> <h3>In</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.In = </span><span class="nx">class</span> <span class="nx">In</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="k">super</span> <span class="nx">idt</span><span class="p">,</span> <span class="nx">@constructor</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="nx">@operator</span></pre></div> </td> </tr> <tr id="section-113"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-113">&#182;</a> </div> <h3>In</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.In = </span><span class="nx">class</span> <span class="nx">In</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@object</span><span class="p">,</span> <span class="nx">@array</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;object&#39;</span><span class="p">,</span> <span class="s1">&#39;array&#39;</span><span class="p">]</span>
@@ -1002,6 +1035,7 @@ true
<span class="p">[</span><span class="nx">cmp</span><span class="p">,</span> <span class="nx">cnj</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="p">[</span><span class="s1">&#39; !== &#39;</span><span class="p">,</span> <span class="s1">&#39; &amp;&amp; &#39;</span><span class="p">]</span> <span class="k">else</span> <span class="p">[</span><span class="s1">&#39; === &#39;</span><span class="p">,</span> <span class="s1">&#39; || &#39;</span><span class="p">]</span>
<span class="nv">tests = </span><span class="k">for</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span>
<span class="p">(</span><span class="k">if</span> <span class="nx">i</span> <span class="k">then</span> <span class="nx">ref</span> <span class="k">else</span> <span class="nx">sub</span><span class="p">)</span> <span class="o">+</span> <span class="nx">cmp</span> <span class="o">+</span> <span class="nx">item</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
<span class="k">return</span> <span class="s1">&#39;false&#39;</span> <span class="k">if</span> <span class="nx">tests</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">0</span>
<span class="nv">tests = </span><span class="nx">tests</span><span class="p">.</span><span class="nx">join</span> <span class="nx">cnj</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">tests</span> <span class="k">else</span> <span class="s2">&quot;(#{tests})&quot;</span>
@@ -1014,7 +1048,7 @@ true
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span>
<span class="nx">toString</span><span class="o">:</span> <span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span> <span class="nx">idt</span><span class="p">,</span> <span class="nx">@constructor</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="s1">&#39;!&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-113"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-113">&#182;</a> </div> <h3>Try</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-114"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-114">&#182;</a> </div> <p>A classic <em>try/catch/finally</em> block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Try = </span><span class="nx">class</span> <span class="nx">Try</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="k">super</span> <span class="nx">idt</span><span class="p">,</span> <span class="nx">@constructor</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="s1">&#39;!&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-114"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-114">&#182;</a> </div> <h3>Try</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-115"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-115">&#182;</a> </div> <p>A classic <em>try/catch/finally</em> block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Try = </span><span class="nx">class</span> <span class="nx">Try</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@attempt</span><span class="p">,</span> <span class="nx">@error</span><span class="p">,</span> <span class="nx">@recovery</span><span class="p">,</span> <span class="nx">@ensure</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;attempt&#39;</span><span class="p">,</span> <span class="s1">&#39;recovery&#39;</span><span class="p">,</span> <span class="s1">&#39;ensure&#39;</span><span class="p">]</span>
@@ -1026,7 +1060,7 @@ true
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@attempt = </span><span class="nx">@attempt</span> <span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@attempt</span>
<span class="vi">@recovery = </span><span class="nx">@recovery</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@recovery</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-115"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-115">&#182;</a> </div> <p>Compilation is more or less as you would expect -- the <em>finally</em> clause
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-116">&#182;</a> </div> <p>Compilation is more or less as you would expect -- the <em>finally</em> clause
is optional, the <em>catch</em> is not.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
<span class="nv">errorPart = </span><span class="k">if</span> <span class="nx">@error</span> <span class="k">then</span> <span class="s2">&quot; (#{ @error.compile o }) &quot;</span> <span class="k">else</span> <span class="s1">&#39; &#39;</span>
@@ -1038,16 +1072,16 @@ is optional, the <em>catch</em> is not.</p> </td> <td cl
<span class="s2"> #{@tab}try {</span>
<span class="s2"> #{ @attempt.compile o, LEVEL_TOP }</span>
<span class="s2"> #{@tab}}#{ catchPart or &#39;&#39; }</span>
<span class="s2"> &quot;&quot;&quot;</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@ensure</span> <span class="k">then</span> <span class="s2">&quot; finally {\n#{ @ensure.compile o, LEVEL_TOP }\n#{@tab}}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-116">&#182;</a> </div> <h3>Throw</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-117"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-117">&#182;</a> </div> <p>Simple node to throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Throw = </span><span class="nx">class</span> <span class="nx">Throw</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="s2"> &quot;&quot;&quot;</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@ensure</span> <span class="k">then</span> <span class="s2">&quot; finally {\n#{ @ensure.compile o, LEVEL_TOP }\n#{@tab}}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-117"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-117">&#182;</a> </div> <h3>Throw</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-118"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-118">&#182;</a> </div> <p>Simple node to throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Throw = </span><span class="nx">class</span> <span class="nx">Throw</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;expression&#39;</span><span class="p">]</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="nx">YES</span>
<span class="nx">jumps</span><span class="o">:</span> <span class="nx">NO</span></pre></div> </td> </tr> <tr id="section-118"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-118">&#182;</a> </div> <p>A <strong>Throw</strong> is already a return, of sorts...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">makeReturn</span><span class="o">:</span> <span class="nx">THIS</span>
<span class="nx">jumps</span><span class="o">:</span> <span class="nx">NO</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-119">&#182;</a> </div> <p>A <strong>Throw</strong> is already a return, of sorts...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">makeReturn</span><span class="o">:</span> <span class="nx">THIS</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@tab</span> <span class="o">+</span> <span class="s2">&quot;throw #{ @expression.compile o };&quot;</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-119">&#182;</a> </div> <h3>Existence</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-120">&#182;</a> </div> <p>Checks a variable for existence -- not <em>null</em> and not <em>undefined</em>. This is
<span class="nx">@tab</span> <span class="o">+</span> <span class="s2">&quot;throw #{ @expression.compile o };&quot;</span></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-120">&#182;</a> </div> <h3>Existence</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-121"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-121">&#182;</a> </div> <p>Checks a variable for existence -- not <em>null</em> and not <em>undefined</em>. This is
similar to <code>.nil?</code> in Ruby, and avoids having to consult a JavaScript truth
table.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Existence = </span><span class="nx">class</span> <span class="nx">Existence</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -1060,13 +1094,13 @@ table.</p> </td> <td class="code"> <div cl
<span class="nv">code = </span><span class="nx">@expression</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
<span class="nv">code = </span><span class="k">if</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">check</span> <span class="nx">code</span>
<span class="k">if</span> <span class="nx">@negated</span>
<span class="s2">&quot;typeof #{code} == \&quot;undefined\&quot; || #{code} === null&quot;</span>
<span class="s2">&quot;typeof #{code} === \&quot;undefined\&quot; || #{code} === null&quot;</span>
<span class="k">else</span>
<span class="s2">&quot;typeof #{code} != \&quot;undefined\&quot; &amp;&amp; #{code} !== null&quot;</span>
<span class="s2">&quot;typeof #{code} !== \&quot;undefined\&quot; &amp;&amp; #{code} !== null&quot;</span>
<span class="k">else</span>
<span class="nv">sym = </span><span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="s1">&#39;==&#39;</span> <span class="k">else</span> <span class="s1">&#39;!=&#39;</span>
<span class="s2">&quot;#{code} #{sym} null&quot;</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;=</span> <span class="nx">LEVEL_COND</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-121"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-121">&#182;</a> </div> <h3>Parens</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-122"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-122">&#182;</a> </div> <p>An extra set of parentheses, specified explicitly in the source. At one time
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;=</span> <span class="nx">LEVEL_COND</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-122"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-122">&#182;</a> </div> <h3>Parens</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-123"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-123">&#182;</a> </div> <p>An extra set of parentheses, specified explicitly in the source. At one time
we tried to clean up the results by detecting and removing redundant
parentheses, but no longer -- you can put in as many as you please.</p>
@@ -1087,7 +1121,7 @@ parentheses, but no longer -- you can put in as many as you please.</p>
<span class="nv">code = </span><span class="nx">expr</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span>
<span class="nv">bare = </span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&lt;</span> <span class="nx">LEVEL_OP</span> <span class="o">and</span> <span class="p">(</span><span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Op</span> <span class="o">or</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Call</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">For</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">returns</span><span class="p">))</span>
<span class="k">if</span> <span class="nx">bare</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-123"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-123">&#182;</a> </div> <h3>For</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-124"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-124">&#182;</a> </div> <p>CoffeeScript's replacement for the <em>for</em> loop is our array and object
<span class="k">if</span> <span class="nx">bare</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-124"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-124">&#182;</a> </div> <h3>For</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-125"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-125">&#182;</a> </div> <p>CoffeeScript's replacement for the <em>for</em> loop is our array and object
comprehensions, that compile into <em>for</em> loops here. They also act as an
expression, able to return the result of each filtered iteration.</p>
@@ -1115,54 +1149,55 @@ you can map and filter in a single pass.</p> </td> <td c
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@returns = </span><span class="kc">yes</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-125"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-125">&#182;</a> </div> <p>Welcome to the hairiest method in all of CoffeeScript. Handles the inner
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-126"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-126">&#182;</a> </div> <p>Welcome to the hairiest method in all of CoffeeScript. Handles the inner
loop, filtering, stepping, and result saving for array, object, and range
comprehensions. Some of the generated code can be shared in common, and
some cannot.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">@body</span><span class="p">]</span>
<span class="nv">lastJumps = </span><span class="nx">last</span><span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">)</span><span class="o">?</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span>
<span class="vi">@returns = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">lastJumps</span> <span class="o">and</span> <span class="nx">lastJumps</span> <span class="k">instanceof</span> <span class="nx">Return</span>
<span class="nv">source = </span><span class="k">if</span> <span class="nx">@range</span> <span class="k">then</span> <span class="nx">@source</span><span class="p">.</span><span class="nx">base</span> <span class="k">else</span> <span class="nx">@source</span>
<span class="nv">scope = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
<span class="nv">name = </span><span class="nx">@name</span> <span class="o">and</span> <span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nv">index = </span><span class="nx">@index</span> <span class="o">and</span> <span class="nx">@index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">@body</span><span class="p">]</span>
<span class="nv">lastJumps = </span><span class="nx">last</span><span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">)</span><span class="o">?</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span>
<span class="vi">@returns = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">lastJumps</span> <span class="o">and</span> <span class="nx">lastJumps</span> <span class="k">instanceof</span> <span class="nx">Return</span>
<span class="nv">source = </span><span class="k">if</span> <span class="nx">@range</span> <span class="k">then</span> <span class="nx">@source</span><span class="p">.</span><span class="nx">base</span> <span class="k">else</span> <span class="nx">@source</span>
<span class="nv">scope = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
<span class="nv">name = </span><span class="nx">@name</span> <span class="o">and</span> <span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nv">index = </span><span class="nx">@index</span> <span class="o">and</span> <span class="nx">@index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">immediate</span><span class="o">:</span> <span class="kc">yes</span><span class="p">)</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@pattern</span>
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">immediate</span><span class="o">:</span> <span class="kc">yes</span><span class="p">)</span> <span class="k">if</span> <span class="nx">index</span>
<span class="nv">rvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;results&#39;</span> <span class="k">if</span> <span class="nx">@returns</span>
<span class="nv">ivar = </span><span class="p">(</span><span class="k">if</span> <span class="nx">@range</span> <span class="k">then</span> <span class="nx">name</span> <span class="k">else</span> <span class="nx">index</span><span class="p">)</span> <span class="o">or</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;i&#39;</span>
<span class="nv">name = </span><span class="nx">ivar</span> <span class="k">if</span> <span class="nx">@pattern</span>
<span class="nv">varPart = </span><span class="s1">&#39;&#39;</span>
<span class="nv">guardPart = </span><span class="s1">&#39;&#39;</span>
<span class="nv">defPart = </span><span class="s1">&#39;&#39;</span>
<span class="nv">idt1 = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
<span class="nv">rvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;results&#39;</span> <span class="k">if</span> <span class="nx">@returns</span>
<span class="nv">ivar = </span><span class="p">(</span><span class="k">if</span> <span class="nx">@range</span> <span class="k">then</span> <span class="nx">name</span> <span class="k">else</span> <span class="nx">index</span><span class="p">)</span> <span class="o">or</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;i&#39;</span></pre></div> </td> </tr> <tr id="section-127"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-127">&#182;</a> </div> <p>the <code>_by</code> variable is created twice in <code>Range</code>s if we don't prevent it from being declared here</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">stepvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s2">&quot;step&quot;</span> <span class="k">if</span> <span class="nx">@step</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@range</span>
<span class="nv">name = </span><span class="nx">ivar</span> <span class="k">if</span> <span class="nx">@pattern</span>
<span class="nv">varPart = </span><span class="s1">&#39;&#39;</span>
<span class="nv">guardPart = </span><span class="s1">&#39;&#39;</span>
<span class="nv">defPart = </span><span class="s1">&#39;&#39;</span>
<span class="nv">idt1 = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
<span class="k">if</span> <span class="nx">@range</span>
<span class="nv">forPart = </span><span class="nx">source</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nx">index</span><span class="o">:</span> <span class="nx">ivar</span><span class="p">,</span> <span class="nx">@step</span><span class="p">})</span>
<span class="k">else</span>
<span class="nv">svar = </span><span class="nx">@source</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nv">svar = </span><span class="nx">@source</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">name</span> <span class="o">or</span> <span class="nx">@own</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">svar</span>
<span class="nv">defPart = </span><span class="s2">&quot;#{@tab}#{ref = scope.freeVariable &#39;ref&#39;} = #{svar};\n&quot;</span>
<span class="nv">svar = </span><span class="nx">ref</span>
<span class="nv">defPart = </span><span class="s2">&quot;#{@tab}#{ref = scope.freeVariable &#39;ref&#39;} = #{svar};\n&quot;</span>
<span class="nv">svar = </span><span class="nx">ref</span>
<span class="k">if</span> <span class="nx">name</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@pattern</span>
<span class="nv">namePart = </span><span class="s2">&quot;#{name} = #{svar}[#{ivar}]&quot;</span>
<span class="nv">namePart = </span><span class="s2">&quot;#{name} = #{svar}[#{ivar}]&quot;</span>
<span class="nx">unless</span> <span class="nx">@object</span>
<span class="nv">lvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;len&#39;</span>
<span class="nv">stepPart = </span><span class="k">if</span> <span class="nx">@step</span> <span class="k">then</span> <span class="s2">&quot;#{ivar} += #{ @step.compile(o, LEVEL_OP) }&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{ivar}++&quot;</span>
<span class="nv">forPart = </span><span class="s2">&quot;#{ivar} = 0, #{lvar} = #{svar}.length; #{ivar} &lt; #{lvar}; #{stepPart}&quot;</span>
<span class="nv">lvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">&#39;len&#39;</span>
<span class="nv">forVarPart = </span><span class="s2">&quot;#{ivar} = 0, #{lvar} = #{svar}.length&quot;</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@step</span> <span class="k">then</span> <span class="s2">&quot;, #{stepvar} = #{@step.compile(o, LEVEL_OP)}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">stepPart = </span><span class="k">if</span> <span class="nx">@step</span> <span class="k">then</span> <span class="s2">&quot;#{ivar} += #{stepvar}&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{ivar}++&quot;</span>
<span class="nv">forPart = </span><span class="s2">&quot;#{forVarPart}; #{ivar} &lt; #{lvar}; #{stepPart}&quot;</span>
<span class="k">if</span> <span class="nx">@returns</span>
<span class="nv">resultPart = </span><span class="s2">&quot;#{@tab}#{rvar} = [];\n&quot;</span>
<span class="nv">returnResult = </span><span class="s2">&quot;\n#{@tab}return #{rvar};&quot;</span>
<span class="nv">body = </span><span class="nx">Push</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">rvar</span><span class="p">,</span> <span class="nx">body</span>
<span class="nv">resultPart = </span><span class="s2">&quot;#{@tab}#{rvar} = [];\n&quot;</span>
<span class="nv">returnResult = </span><span class="s2">&quot;\n#{@tab}return #{rvar};&quot;</span>
<span class="nv">body = </span><span class="nx">Push</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">rvar</span><span class="p">,</span> <span class="nx">body</span>
<span class="k">if</span> <span class="nx">@guard</span>
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="k">new</span> <span class="nx">If</span> <span class="nx">@guard</span><span class="p">,</span> <span class="nx">body</span><span class="p">]</span>
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="k">new</span> <span class="nx">If</span> <span class="nx">@guard</span><span class="p">,</span> <span class="nx">body</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">@pattern</span>
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">@name</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s2">&quot;#{svar}[#{ivar}]&quot;</span>
<span class="nx">defPart</span> <span class="o">+=</span> <span class="nx">@pluckDirectCall</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">body</span>
<span class="nv">varPart = </span><span class="s2">&quot;\n#{idt1}#{namePart};&quot;</span> <span class="k">if</span> <span class="nx">namePart</span>
<span class="nx">defPart</span> <span class="o">+=</span> <span class="nx">@pluckDirectCall</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">body</span>
<span class="nv">varPart = </span><span class="s2">&quot;\n#{idt1}#{namePart};&quot;</span> <span class="k">if</span> <span class="nx">namePart</span>
<span class="k">if</span> <span class="nx">@object</span>
<span class="nv">forPart = </span><span class="s2">&quot;#{ivar} in #{svar}&quot;</span>
<span class="nv">guardPart = </span><span class="s2">&quot;\n#{idt1}if (!#{utility(&#39;hasProp&#39;)}.call(#{svar}, #{ivar})) continue;&quot;</span> <span class="k">if</span> <span class="nx">@own</span>
<span class="nv">body = </span><span class="nx">body</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">indent</span><span class="o">:</span> <span class="nx">idt1</span><span class="p">),</span> <span class="nx">LEVEL_TOP</span>
<span class="nv">body = </span><span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">body</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span> <span class="k">if</span> <span class="nx">body</span>
<span class="nv">forPart = </span><span class="s2">&quot;#{ivar} in #{svar}&quot;</span>
<span class="nv">guardPart = </span><span class="s2">&quot;\n#{idt1}if (!#{utility(&#39;hasProp&#39;)}.call(#{svar}, #{ivar})) continue;&quot;</span> <span class="k">if</span> <span class="nx">@own</span>
<span class="nv">body = </span><span class="nx">body</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">indent</span><span class="o">:</span> <span class="nx">idt1</span><span class="p">),</span> <span class="nx">LEVEL_TOP</span>
<span class="nv">body = </span><span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">body</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span> <span class="k">if</span> <span class="nx">body</span>
<span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> #{defPart}#{resultPart or &#39;&#39;}#{@tab}for (#{forPart}) {#{guardPart}#{varPart}#{body}#{@tab}}#{returnResult or &#39;&#39;}</span>
<span class="s2"> &quot;&quot;&quot;</span>
@@ -1186,7 +1221,7 @@ some cannot.</p> </td> <td class="code"> <
<span class="nx">args</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;this&#39;</span>
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">base</span><span class="p">,</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">args</span>
<span class="nx">defs</span> <span class="o">+=</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">ref</span><span class="p">,</span> <span class="nx">fn</span><span class="p">).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;;\n&#39;</span>
<span class="nx">defs</span></pre></div> </td> </tr> <tr id="section-126"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-126">&#182;</a> </div> <h3>Switch</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-127"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-127">&#182;</a> </div> <p>A JavaScript <em>switch</em> statement. Converts into a returnable expression on-demand.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Switch = </span><span class="nx">class</span> <span class="nx">Switch</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">defs</span></pre></div> </td> </tr> <tr id="section-128"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-128">&#182;</a> </div> <h3>Switch</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-129"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-129">&#182;</a> </div> <p>A JavaScript <em>switch</em> statement. Converts into a returnable expression on-demand.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Switch = </span><span class="nx">class</span> <span class="nx">Switch</span> <span class="k">extends</span> <span class="nx">Base</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@subject</span><span class="p">,</span> <span class="nx">@cases</span><span class="p">,</span> <span class="nx">@otherwise</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;subject&#39;</span><span class="p">,</span> <span class="s1">&#39;cases&#39;</span><span class="p">,</span> <span class="s1">&#39;otherwise&#39;</span><span class="p">]</span>
@@ -1217,7 +1252,7 @@ some cannot.</p> </td> <td class="code"> <
<span class="k">continue</span> <span class="k">if</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Return</span> <span class="o">or</span> <span class="p">(</span><span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">value</span> <span class="o">isnt</span> <span class="s1">&#39;debugger&#39;</span><span class="p">)</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">idt2</span> <span class="o">+</span> <span class="s1">&#39;break;\n&#39;</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">idt1</span> <span class="o">+</span> <span class="s2">&quot;default:\n#{ @otherwise.compile o, LEVEL_TOP }\n&quot;</span> <span class="k">if</span> <span class="nx">@otherwise</span> <span class="o">and</span> <span class="nx">@otherwise</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">code</span> <span class="o">+</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="s1">&#39;}&#39;</span></pre></div> </td> </tr> <tr id="section-128"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-128">&#182;</a> </div> <h3>If</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-129"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-129">&#182;</a> </div> <p><em>If/else</em> statements. Acts as an expression by pushing down requested returns
<span class="nx">code</span> <span class="o">+</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="s1">&#39;}&#39;</span></pre></div> </td> </tr> <tr id="section-130"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-130">&#182;</a> </div> <h3>If</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-131"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-131">&#182;</a> </div> <p><em>If/else</em> statements. Acts as an expression by pushing down requested returns
to the last line of each clause.</p>
<p>Single-expression <strong>Ifs</strong> are compiled into conditional operators if possible,
@@ -1231,13 +1266,13 @@ because ternaries are already proper expressions, and don't need conversion.</p>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;condition&#39;</span><span class="p">,</span> <span class="s1">&#39;body&#39;</span><span class="p">,</span> <span class="s1">&#39;elseBody&#39;</span><span class="p">]</span>
<span class="nx">bodyNode</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="nx">@body</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
<span class="nx">elseBodyNode</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="nx">@elseBody</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-130"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-130">&#182;</a> </div> <p>Rewrite a chain of <strong>Ifs</strong> to add a default case as the final <em>else</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addElse</span><span class="o">:</span> <span class="p">(</span><span class="nx">elseBody</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">elseBodyNode</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="nx">@elseBody</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-132"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-132">&#182;</a> </div> <p>Rewrite a chain of <strong>Ifs</strong> to add a default case as the final <em>else</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addElse</span><span class="o">:</span> <span class="p">(</span><span class="nx">elseBody</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@isChain</span>
<span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nx">addElse</span> <span class="nx">elseBody</span>
<span class="k">else</span>
<span class="vi">@isChain = </span><span class="nx">elseBody</span> <span class="k">instanceof</span> <span class="nx">If</span>
<span class="vi">@elseBody = </span><span class="nx">@ensureBlock</span> <span class="nx">elseBody</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-131"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-131">&#182;</a> </div> <p>The <strong>If</strong> only compiles into a statement if either of its bodies needs
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-133"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-133">&#182;</a> </div> <p>The <strong>If</strong> only compiles into a statement if either of its bodies needs
to be a statement. Otherwise a conditional operator is safe.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">isStatement</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">o</span><span class="o">?</span><span class="p">.</span><span class="nx">level</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span> <span class="o">or</span>
<span class="nx">@bodyNode</span><span class="p">().</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@elseBodyNode</span><span class="p">()</span><span class="o">?</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
@@ -1253,7 +1288,7 @@ to be a statement. Otherwise a conditional operator is safe.</p> </t
<span class="k">this</span>
<span class="nx">ensureBlock</span><span class="o">:</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Block</span> <span class="k">then</span> <span class="nx">node</span> <span class="k">else</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="nx">node</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-132"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-132">&#182;</a> </div> <p>Compile the <strong>If</strong> as a regular <em>if-else</em> statement. Flattened chains
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Block</span> <span class="k">then</span> <span class="nx">node</span> <span class="k">else</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="nx">node</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-134"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-134">&#182;</a> </div> <p>Compile the <strong>If</strong> as a regular <em>if-else</em> statement. Flattened chains
force inner <em>else</em> bodies into statement form.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileStatement</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">child = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;chainChild&#39;</span>
<span class="nv">cond = </span><span class="nx">@condition</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span>
@@ -1268,7 +1303,7 @@ force inner <em>else</em> bodies into statement form.</p> </td>
<span class="nv">o.chainChild = </span><span class="kc">yes</span>
<span class="nx">@elseBody</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span>
<span class="k">else</span>
<span class="s2">&quot;{\n#{ @elseBody.compile o, LEVEL_TOP }\n#{@tab}}&quot;</span></pre></div> </td> </tr> <tr id="section-133"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-133">&#182;</a> </div> <p>Compile the If as a conditional operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileExpression</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;{\n#{ @elseBody.compile o, LEVEL_TOP }\n#{@tab}}&quot;</span></pre></div> </td> </tr> <tr id="section-135"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-135">&#182;</a> </div> <p>Compile the If as a conditional operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileExpression</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">cond = </span><span class="nx">@condition</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_COND</span>
<span class="nv">body = </span><span class="nx">@bodyNode</span><span class="p">().</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
<span class="nv">alt = </span><span class="k">if</span> <span class="nx">@elseBodyNode</span><span class="p">()</span> <span class="k">then</span> <span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;void 0&#39;</span>
@@ -1276,21 +1311,20 @@ force inner <em>else</em> bodies into statement form.</p> </td>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">&gt;=</span> <span class="nx">LEVEL_COND</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span>
<span class="nx">unfoldSoak</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@soak</span> <span class="o">and</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-134"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-134">&#182;</a> </div> <h2>Faux-Nodes</h2>
<span class="nx">@soak</span> <span class="o">and</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-136"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-136">&#182;</a> </div> <h2>Faux-Nodes</h2>
<p>Faux-nodes are never created by the grammar, but are used during code
generation to generate other combinations of nodes.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-135"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-135">&#182;</a> </div> <h3>Push</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-136"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-136">&#182;</a> </div> <p>The <strong>Push</strong> creates the tree for <code>array.push(value)</code>,
generation to generate other combinations of nodes.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-137"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-137">&#182;</a> </div> <h3>Push</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-138"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-138">&#182;</a> </div> <p>The <strong>Push</strong> creates the tree for <code>array.push(value)</code>,
which is helpful for recording the result arrays from comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Push =</span>
<span class="nx">wrap</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">exps</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">exps</span> <span class="k">if</span> <span class="nx">exps</span><span class="p">.</span><span class="nx">isEmpty</span><span class="p">()</span> <span class="o">or</span> <span class="nx">last</span><span class="p">(</span><span class="nx">exps</span><span class="p">.</span><span class="nx">expressions</span><span class="p">).</span><span class="nx">jumps</span><span class="p">()</span>
<span class="nx">exps</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Call</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;push&#39;</span><span class="p">]),</span> <span class="p">[</span><span class="nx">exps</span><span class="p">.</span><span class="nx">pop</span><span class="p">()]</span></pre></div> </td> </tr> <tr id="section-137"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-137">&#182;</a> </div> <h3>Closure</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-138"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-138">&#182;</a> </div> <p>A faux-node used to wrap an expressions body in a closure.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Closure =</span></pre></div> </td> </tr> <tr id="section-139"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-139">&#182;</a> </div> <p>Wrap the expressions body, unless it contains a pure statement,
<span class="nx">exps</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Call</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;push&#39;</span><span class="p">]),</span> <span class="p">[</span><span class="nx">exps</span><span class="p">.</span><span class="nx">pop</span><span class="p">()]</span></pre></div> </td> </tr> <tr id="section-139"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-139">&#182;</a> </div> <h3>Closure</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-140"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-140">&#182;</a> </div> <p>A faux-node used to wrap an expressions body in a closure.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Closure =</span></pre></div> </td> </tr> <tr id="section-141"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-141">&#182;</a> </div> <p>Wrap the expressions body, unless it contains a pure statement,
in which case, no dice. If the body mentions <code>this</code> or <code>arguments</code>,
then make sure that the closure wrapper preserves the original values.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">wrap</span><span class="o">:</span> <span class="p">(</span><span class="nx">expressions</span><span class="p">,</span> <span class="nx">statement</span><span class="p">,</span> <span class="nx">noReturn</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">expressions</span> <span class="k">if</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span>
<span class="nv">func = </span><span class="k">new</span> <span class="nx">Code</span> <span class="p">[],</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">expressions</span><span class="p">]</span>
<span class="nv">args = </span><span class="p">[]</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">mentionsArgs = </span><span class="nx">expressions</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">@literalArgs</span><span class="p">)</span> <span class="o">or</span>
<span class="p">(</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">@literalThis</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">mentionsArgs = </span><span class="nx">expressions</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">@literalArgs</span><span class="p">)</span> <span class="o">or</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">@literalThis</span>
<span class="nv">meth = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="k">if</span> <span class="nx">mentionsArgs</span> <span class="k">then</span> <span class="s1">&#39;apply&#39;</span> <span class="k">else</span> <span class="s1">&#39;call&#39;</span>
<span class="nv">args = </span><span class="p">[</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;this&#39;</span><span class="p">]</span>
<span class="nx">args</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;arguments&#39;</span> <span class="k">if</span> <span class="nx">mentionsArgs</span>
@@ -1303,11 +1337,11 @@ then make sure that the closure wrapper preserves the original values.</p>
<span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;arguments&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">asKey</span>
<span class="nx">literalThis</span><span class="o">:</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;this&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">asKey</span><span class="p">)</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">bound</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-140"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-140">&#182;</a> </div> <p>Unfold a node's child if soak, then tuck the node under created <code>If</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">unfoldSoak = </span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">parent</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">bound</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-142"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-142">&#182;</a> </div> <p>Unfold a node's child if soak, then tuck the node under created <code>If</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">unfoldSoak = </span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">parent</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">ifn = </span><span class="nx">parent</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">unfoldSoak</span> <span class="nx">o</span>
<span class="nx">parent</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">ifn</span><span class="p">.</span><span class="nx">body</span>
<span class="nv">ifn.body = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">parent</span>
<span class="nx">ifn</span></pre></div> </td> </tr> <tr id="section-141"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-141">&#182;</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre><span class="nv">UTILITIES =</span></pre></div> </td> </tr> <tr id="section-142"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-142">&#182;</a> </div> <p>Correctly set up a prototype chain for inheritance, including a reference
<span class="nx">ifn</span></pre></div> </td> </tr> <tr id="section-143"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-143">&#182;</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre><span class="nv">UTILITIES =</span></pre></div> </td> </tr> <tr id="section-144"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-144">&#182;</a> </div> <p>Correctly set up a prototype chain for inheritance, including a reference
to the superclass for <code>super()</code> calls, and copies of any static properties.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">extends</span><span class="o">:</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> function(child, parent) {</span>
<span class="s1"> for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }</span>
@@ -1317,27 +1351,26 @@ to the superclass for <code>super()</code> calls, and copies of any static prope
<span class="s1"> child.__super__ = parent.prototype;</span>
<span class="s1"> return child;</span>
<span class="s1"> }</span>
<span class="s1"> &#39;&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-143"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-143">&#182;</a> </div> <p>Create a function bound to the current value of "this".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">bind</span><span class="o">:</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> &#39;&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-145"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-145">&#182;</a> </div> <p>Create a function bound to the current value of "this".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">bind</span><span class="o">:</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> function(fn, me){ return function(){ return fn.apply(me, arguments); }; }</span>
<span class="s1"> &#39;&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-144"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-144">&#182;</a> </div> <p>Discover if an item is in an array.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indexOf</span><span class="o">:</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> &#39;&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-146"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-146">&#182;</a> </div> <p>Discover if an item is in an array.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indexOf</span><span class="o">:</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> Array.prototype.indexOf || function(item) {</span>
<span class="s1"> for (var i = 0, l = this.length; i &lt; l; i++) {</span>
<span class="s1"> if (this[i] === item) return i;</span>
<span class="s1"> }</span>
<span class="s1"> return -1;</span>
<span class="s1"> }</span>
<span class="s1"> &#39;&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-145"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-145">&#182;</a> </div> <p>Shortcuts to speed up the lookup time for native functions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasProp</span><span class="o">:</span> <span class="s1">&#39;Object.prototype.hasOwnProperty&#39;</span>
<span class="nx">slice</span> <span class="o">:</span> <span class="s1">&#39;Array.prototype.slice&#39;</span></pre></div> </td> </tr> <tr id="section-146"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-146">&#182;</a> </div> <p>Levels indicates a node's position in the AST. Useful for knowing if
<span class="s1"> &#39;&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-147"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-147">&#182;</a> </div> <p>Shortcuts to speed up the lookup time for native functions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasProp</span><span class="o">:</span> <span class="s1">&#39;Object.prototype.hasOwnProperty&#39;</span>
<span class="nx">slice</span> <span class="o">:</span> <span class="s1">&#39;Array.prototype.slice&#39;</span></pre></div> </td> </tr> <tr id="section-148"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-148">&#182;</a> </div> <p>Levels indicates a node's position in the AST. Useful for knowing if
parens are necessary or superfluous.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LEVEL_TOP = </span><span class="mi">1</span> <span class="c1"># ...;</span>
<span class="nv">LEVEL_PAREN = </span><span class="mi">2</span> <span class="c1"># (...)</span>
<span class="nv">LEVEL_LIST = </span><span class="mi">3</span> <span class="c1"># [...]</span>
<span class="nv">LEVEL_COND = </span><span class="mi">4</span> <span class="c1"># ... ? x : y</span>
<span class="nv">LEVEL_OP = </span><span class="mi">5</span> <span class="c1"># !...</span>
<span class="nv">LEVEL_ACCESS = </span><span class="mi">6</span> <span class="c1"># ...[0]</span></pre></div> </td> </tr> <tr id="section-147"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-147">&#182;</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB = </span><span class="s1">&#39; &#39;</span></pre></div> </td> </tr> <tr id="section-148"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-148">&#182;</a> </div> <p>Trim out all trailing whitespace, so that the generated code plays nice
with Git.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TRAILING_WHITESPACE = </span><span class="sr">/[ \t]+$/gm</span>
<span class="nv">LEVEL_ACCESS = </span><span class="mi">6</span> <span class="c1"># ...[0]</span></pre></div> </td> </tr> <tr id="section-149"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-149">&#182;</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB = </span><span class="s1">&#39; &#39;</span>
<span class="nv">IDENTIFIER = </span><span class="sr">/^[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*$/</span>
<span class="nv">SIMPLENUM = </span><span class="sr">/^[+-]?\d+$/</span></pre></div> </td> </tr> <tr id="section-149"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-149">&#182;</a> </div> <p>Is a literal value a string?</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IS_STRING = </span><span class="sr">/^[&#39;&quot;]/</span></pre></div> </td> </tr> <tr id="section-150"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-150">&#182;</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-151"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-151">&#182;</a> </div> <p>Helper for ensuring that utility functions are assigned at the top level.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">utility = </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">SIMPLENUM = </span><span class="sr">/^[+-]?\d+$/</span></pre></div> </td> </tr> <tr id="section-150"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-150">&#182;</a> </div> <p>Is a literal value a string?</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IS_STRING = </span><span class="sr">/^[&#39;&quot;]/</span></pre></div> </td> </tr> <tr id="section-151"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-151">&#182;</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-152"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-152">&#182;</a> </div> <p>Helper for ensuring that utility functions are assigned at the top level.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">utility = </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">ref = </span><span class="s2">&quot;__#{name}&quot;</span>
<span class="nx">Scope</span><span class="p">.</span><span class="nx">root</span><span class="p">.</span><span class="nx">assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">UTILITIES</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="nx">ref</span>

View File

@@ -4,22 +4,57 @@ Using it looks like this:</p>
<pre><code>coffee&gt; console.log "#{num} bottles of beer" for num in [99..1]
</code></pre> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>Require the <strong>coffee-script</strong> module to get access to the compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">&#39;./coffee-script&#39;</span>
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s1">&#39;./helpers&#39;</span>
<span class="nv">readline = </span><span class="nx">require</span> <span class="s1">&#39;readline&#39;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Start by opening up <code>stdin</code> and <code>stdout</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
<span class="nv">stdout = </span><span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Log an error.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">error = </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">())</span> <span class="o">+</span> <span class="s1">&#39;\n\n&#39;</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Quick alias for quitting the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="nx">quit</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
<span class="nv">readline = </span><span class="nx">require</span> <span class="s1">&#39;readline&#39;</span>
<span class="p">{</span><span class="nx">inspect</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;util&#39;</span>
<span class="p">{</span><span class="nx">Script</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;vm&#39;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>REPL Setup</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Config</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">enableColours = </span><span class="kc">no</span>
<span class="nx">unless</span> <span class="nx">process</span><span class="p">.</span><span class="nx">platform</span> <span class="o">is</span> <span class="s1">&#39;win32&#39;</span>
<span class="nv">enableColours = </span><span class="o">not</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NODE_DISABLE_COLORS</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Start by opening up <code>stdin</code> and <code>stdout</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
<span class="nv">stdout = </span><span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Log an error.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">error = </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">())</span> <span class="o">+</span> <span class="s1">&#39;\n\n&#39;</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>The current backlog of multi-line code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">backlog = </span><span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
Attempt to evaluate the command. If there's an exception, print it out instead
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">try</span>
<span class="nv">val = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">bare</span><span class="o">:</span> <span class="kc">on</span><span class="p">,</span> <span class="nx">globals</span><span class="o">:</span> <span class="kc">on</span><span class="p">,</span> <span class="nx">filename</span><span class="o">:</span> <span class="s1">&#39;repl&#39;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">val</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span> <span class="k">if</span> <span class="nx">val</span> <span class="o">isnt</span> <span class="kc">undefined</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nx">error</span> <span class="nx">err</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Make sure that uncaught exceptions don't kill the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;uncaughtException&#39;</span><span class="p">,</span> <span class="nx">error</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">3</span>
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span>
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run = </span><span class="nx">do</span> <span class="o">-&gt;</span>
<span class="nv">sandbox =</span>
<span class="nx">require</span><span class="o">:</span> <span class="nx">require</span>
<span class="nx">module</span> <span class="o">:</span> <span class="p">{</span> <span class="nx">exports</span><span class="o">:</span> <span class="p">{}</span> <span class="p">}</span>
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="o">=</span> <span class="nx">global</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="k">for</span> <span class="nx">g</span> <span class="k">of</span> <span class="nx">global</span>
<span class="nv">sandbox.global = </span><span class="nx">sandbox</span>
<span class="nv">sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = </span><span class="nx">sandbox</span>
<span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">code = </span><span class="nx">backlog</span> <span class="o">+=</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">code</span><span class="p">[</span><span class="nx">code</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;\\&#39;</span>
<span class="k">return</span> <span class="nv">backlog = </span><span class="nx">backlog</span><span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">backlog</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="nv">backlog = </span><span class="s1">&#39;&#39;</span>
<span class="k">try</span>
<span class="nv">val = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="nx">code</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">sandbox</span><span class="p">,</span>
<span class="nx">bare</span><span class="o">:</span> <span class="kc">on</span><span class="p">,</span>
<span class="nx">filename</span><span class="o">:</span> <span class="s1">&#39;repl&#39;</span>
<span class="p">}</span>
<span class="nx">unless</span> <span class="nx">val</span> <span class="o">is</span> <span class="kc">undefined</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">inspect</span><span class="p">(</span><span class="nx">val</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">enableColours</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nx">error</span> <span class="nx">err</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <h1>Autocompletion</h1> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Regexes to match complete-able bits of text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSOR = </span><span class="sr">/\s*([\w\.]+)(?:\.(\w*))$/</span>
<span class="nv">SIMPLEVAR = </span><span class="sr">/\s*(\w*)$/i</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Returns a list of completions, and the completed text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">autocomplete = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">completeAttribute</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="nx">completeVariable</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="p">[[],</span> <span class="nx">text</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Attempt to autocomplete a chained dotted attribute: <code>one.two.three</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeAttribute = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nv">match = </span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ACCESSOR</span>
<span class="p">[</span><span class="nx">all</span><span class="p">,</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span> <span class="o">=</span> <span class="nx">match</span>
<span class="k">try</span>
<span class="nv">val = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">obj</span>
<span class="k">catch</span> <span class="nx">error</span>
<span class="k">return</span> <span class="p">[[],</span> <span class="nx">text</span><span class="p">]</span>
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">prefix</span><span class="p">,</span> <span class="nx">getPropertyNames</span> <span class="nx">val</span>
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Attempt to autocomplete an in-scope free variable: <code>one</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeVariable = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nv">free = </span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLEVAR</span><span class="p">)</span><span class="o">?</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nv">scope = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="s1">&#39;this&#39;</span>
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">free</span><span class="p">,</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">RESERVED</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">getPropertyNames</span> <span class="nx">scope</span><span class="p">)</span>
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">free</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Return elements of candidates for which <code>prefix</code> is a prefix.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">getCompletions = </span><span class="p">(</span><span class="nx">prefix</span><span class="p">,</span> <span class="nx">candidates</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">el</span> <span class="k">for</span> <span class="nx">el</span> <span class="k">in</span> <span class="nx">candidates</span> <span class="k">when</span> <span class="nx">el</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">prefix</span><span class="p">)</span> <span class="o">is</span> <span class="mi">0</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Return all "own" properties of an object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">getPropertyNames = </span><span class="p">(</span><span class="nx">obj</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">name</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">name</span> <span class="k">of</span> <span class="nx">obj</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Make sure that uncaught exceptions don't kill the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;uncaughtException&#39;</span><span class="p">,</span> <span class="nx">error</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">3</span>
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">autocomplete</span>
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">buffer</span>
<span class="k">else</span>
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">stdout</span>
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">stdout</span><span class="p">,</span> <span class="nx">autocomplete</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="s1">&#39;coffee&gt; &#39;</span>
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;close&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">stdin</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>

View File

@@ -78,7 +78,10 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
<span class="o">not</span> <span class="p">(</span><span class="nx">two</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;:&#39;</span> <span class="o">or</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;@&#39;</span> <span class="o">and</span> <span class="nx">three</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;:&#39;</span><span class="p">))</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;,&#39;</span> <span class="o">and</span> <span class="nx">one</span> <span class="o">and</span>
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">])</span>
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;}&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">tok = </span><span class="p">[</span><span class="s1">&#39;}&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nv">tok.generated = </span><span class="kc">yes</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;{&#39;</span> <span class="k">then</span> <span class="s1">&#39;{&#39;</span> <span class="k">else</span> <span class="nx">tag</span><span class="p">),</span> <span class="nx">i</span><span class="p">]</span>
@@ -114,6 +117,7 @@ deal with them.</p> </td> <td class="code">
<span class="nv">seenSingle = </span><span class="kc">no</span>
<span class="nv">noCall = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">callObject</span> <span class="o">or</span>
<span class="nx">prev</span><span class="o">?</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">.</span><span class="nx">call</span> <span class="o">or</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span><span class="p">)</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_CALL</span> <span class="o">or</span> <span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">newLine</span><span class="p">)</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_UNSPACED_CALL</span><span class="p">)</span>

View File

@@ -8,7 +8,7 @@ with the outside.</p> </td> <td class="code">
<span class="nv">exports.Scope = </span><span class="nx">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@root</span><span class="o">:</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
as well as a reference to the <strong>Block</strong> node is belongs to, which is
where it should declare its variables, and a reference to the function that
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</span><span class="p">(</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">)</span> <span class="o">-&gt;</span>
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@variables = </span><span class="p">[{</span><span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;arguments&#39;</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;arguments&#39;</span><span class="p">}]</span>
<span class="vi">@positions = </span><span class="p">{}</span>
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">@parent</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">add</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -36,7 +36,7 @@ walks up to the root scope.</p> </td> <td class="code">
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">freeVariable</span><span class="o">:</span> <span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">index = </span><span class="mi">0</span>
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">),</span> <span class="kc">true</span><span class="p">)</span>
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">))</span>
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s1">&#39;var&#39;</span><span class="p">,</span> <span class="kc">yes</span>
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assign</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-&gt;</span>

View File

@@ -80,10 +80,10 @@
<div class="screenshadow bl"></div>
<div class="screenshadow br"></div>
<div id="repl_source_wrap">
<textarea id="repl_source" rows="100">alert "Hello CoffeeScript!"</textarea>
<textarea id="repl_source" rows="100" spellcheck="false">alert "Hello CoffeeScript!"</textarea>
</div>
<div id="repl_results_wrap"><pre id="repl_results"></pre></div>
<div class="minibutton dark run">Run</div>
<div class="minibutton dark run" title="Ctrl-Enter">Run</div>
<br class="clear" />
</div>
</div>
@@ -131,7 +131,7 @@
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.0.1">1.0.1</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.1.1">1.1.1</a>
</p>
<h2>
@@ -166,17 +166,21 @@
</p>
<pre>
npm install coffee-script</pre>
npm install -g coffee-script</pre>
<p>
If you'd prefer to install the latest master version of CoffeeScript, you
can clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
<p>
(Leave off the <tt>-g</tt> if you don't wish to install globally.)
</p>
<p>
If you'd prefer to install the latest master version of CoffeeScript, you
can clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
<pre>
sudo bin/cake install</pre>
@@ -219,10 +223,11 @@ sudo bin/cake install</pre>
</td>
</tr>
<tr>
<td><code>-j, --join</code></td>
<td><code>-j, --join [FILE]</code></td>
<td>
Before compiling, concatenate all scripts together in the order they
were passed. Useful for building large projects.
were passed, and write them into the specified file.
Useful for building large projects.
</td>
</tr>
<tr>
@@ -326,7 +331,7 @@ Expressions
</li>
<li>
Concatenate a list of files into a single script:<br />
<tt>coffee -o lib/ --join --compile src/*.coffee</tt>
<tt>coffee --join project.js --compile src/*.coffee</tt>
</li>
<li>
Print out the compiled JS from a one-liner:<br />
@@ -542,7 +547,7 @@ Expressions
<b class="header">Array Slicing and Splicing with Ranges</b>
Ranges can also be used to extract slices of arrays.
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
with three docs (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
with three dots (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
</p>
<%= code_for('slices', 'middle') %>
<p>
@@ -701,15 +706,15 @@ Expressions
in a single assignable expression.
</p>
<p>
Constructor functions are named, to better support reflection. In the
example below for the first class, <tt>this.constructor.name is "Animal"</tt>.
Constructor functions are named, to better support helpful stack traces.
</p>
<%= code_for('classes', true) %>
<p>
If structuring your prototypes classically isn't your cup of tea, CoffeeScript
provides a couple of lower-level conveniences. The <tt>extends</tt> operator
helps with proper prototype setup, <tt>::</tt> gives you
quick access to an object's prototype, and <tt>super()</tt>
helps with proper prototype setup, and can be used to create an inheritance
chain between any pair of constructor functions; <tt>::</tt> gives you
quick access to an object's prototype; and <tt>super()</tt>
is converted into a call against the immediate ancestor's method of the same name.
</p>
<%= code_for('prototypes', '"one_two".dasherize()') %>
@@ -842,7 +847,7 @@ Expressions
<p>
Sometimes you'd like to pass a block comment through to the generated
JavaScript. For example, when you need to embed a licensing header at
the top of a file. Block comments, which mirror the synax for heredocs,
the top of a file. Block comments, which mirror the syntax for heredocs,
are preserved in the generated code.
</p>
<%= code_for('block_comment') %>
@@ -923,6 +928,10 @@ Expressions
</h2>
<ul>
<li>
<b>sstephenson</b>'s <a href="http://pow.cx/">Pow</a>,
a zero-configuration Rack server, with comprehensive annotated source.
</li>
<li>
<b>frank06</b>'s <a href="http://riakjs.org/">riak-js</a>, a Node.js client for
<a href="http://www.basho.com/Riak.html">Riak</a>, with support for HTTP
@@ -932,6 +941,10 @@ Expressions
<b>technoweenie</b>'s <a href="https://github.com/technoweenie/coffee-resque">Coffee-Resque</a>,
a port of <a href="https://github.com/defunkt/resque">Resque</a> for Node.js.
</li>
<li>
<b>assaf</b>'s <a href="http://zombie.labnotes.org/">Zombie.js</a>,
A headless, full-stack, faux-browser testing library for Node.js.
</li>
<li>
<b>jashkenas</b>' <a href="documentation/docs/underscore.html">Underscore.coffee</a>, a port
of the <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
@@ -945,10 +958,6 @@ Expressions
<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.
</li>
<li>
<b>sstephenson</b>'s <a href="http://sstephenson.github.com/strscan-js/">StringScanner</a>,
a simple tokenizer and lexical scanner for JavaScript strings.
</li>
</ul>
<h2>
@@ -971,102 +980,23 @@ Expressions
</li>
<li>
<a href="http://github.com/jashkenas/coffee-script/issues">CoffeeScript Issues</a><br />
Bugs reports, feature requests, and general discussion all belong here.
Bug reports, feature proposals, and ideas for changes to the language belong here.
</li>
<li>
If you'd like to chat, stop by <tt>#coffeescript</tt> on Freenode in the
IRC client of your choice, or on
<a href="http://webchat.freenode.net/">webchat.freenode.net</a>.
<a href="https://groups.google.com/forum/#!forum/coffeescript">CoffeeScript Google Group</a><br />
If you'd like to ask a question, the mailing list is a good place to get help.
</li>
<li>
<b>satyr</b>'s <a href="http://github.com/satyr/coco">Coco</a>
&mdash; An avant-garde dialect of CoffeeScript that frequently pioneers
features and optimizations, some of which CoffeeScript later adopts.
Check out the <a href="https://github.com/satyr/coco/wiki/additions">list of additions</a>
to the language.
<a href="http://github.com/jashkenas/coffee-script/wiki">The CoffeeScript Wiki</a><br />
If you've ever learned a neat CoffeeScript tip or trick, or ran into a gotcha &mdash; share it on the wiki.
The wiki also serves as a directory of handy
<a href="http://github.com/jashkenas/coffee-script/wiki/Text-editor-plugins">text editor extensions</a>,
<a href="http://github.com/jashkenas/coffee-script/wiki/Web-framework-plugins">web framework plugins</a>,
and general <a href="http://github.com/jashkenas/coffee-script/wiki/Build-tools">CoffeeScript build tools</a>.
</li>
<li>
<b>yeungda</b>'s <a href="http://github.com/yeungda/jcoffeescript">JCoffeeScript</a>
&mdash; A Java Library that uses Rhino to compile CoffeeScript, allowing
compilation within Java projects or on systems that Node.js doesn't support.
</li>
<li>
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
&mdash; a Emacs major mode that provides syntax highlighting, indentation
support, and some bonus commands.
</li>
<li>
<b>jashkenas</b>' <a href="http://github.com/jashkenas/coffee-script-tmbundle">CoffeeScript TextMate Bundle</a>
&mdash; which provides syntax highlighting, snippet expansion, and the
ability to run bits of CoffeeScript from within TextMate itself.
</li>
<li>
<b>kchmck</b>'s <a href="http://github.com/kchmck/vim-coffee-script">Vim CoffeeScript</a>
&mdash; which adds Vim syntax highlighting and indentation support.
</li>
<li>
<b>wavded</b>'s <a href="http://github.com/wavded/gedit-coffeescript">gedit-coffeescript</a>
&mdash; a CoffeeScript syntax highlighter for the gedit text editor.
</li>
<li>
<b>yeungda</b>'s <a href="http://yeungda.github.com/coffeescript-idea/">coffeescript-idea</a>
&mdash; a plugin for IntelliJ IDEA and RubyMine providing syntax highlighting.
</li>
<li>
<b>dhotson</b>'s <a href="https://github.com/dhotson/coffeescript-jedit">coffeescript-jedit</a>
&mdash; which provides syntax highlighting support in jEdit.
</li>
<li>
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
&mdash; a small Rack middleware for serving CoffeeScript files as
compiled JavaScript on the fly.
</li>
<li>
<b>jnicklas</b>'s <a href="http://github.com/jnicklas/bistro_car">BistroCar</a>
&mdash; a plugin that serves and bundles CoffeeScript from within your
Rails application.
</li>
<li>
<b>dsc</b>'s <a href="http://github.com/dsc/coffeecup">CoffeeCup</a>
&mdash; a Python WSGI middleware that compiles CoffeeScript to JavaScript
on-demand during development.
</li>
<li>
<b>sutto</b>'s <a href="http://github.com/Sutto/barista">Barista</a>
&mdash; a BistroCar alternative that integrates well with
<a href="http://documentcloud.github.com/jammit">Jammit</a> and Rails 3.
</li>
<li>
<b>inem</b> and <b>gerad</b>'s <a href="http://github.com/gerad/coffee-haml-filter">coffee-haml-filter</a>
&mdash; a custom filter for rendering CoffeeScript inline within
<a href="http://haml-lang.com/">HAML</a> templates.
</li>
<li>
<b>andrzejsliwa</b>'s <a href="http://github.com/andrzejsliwa/coffeeapp">CoffeeApp</a>
&mdash; a CoffeeScript wrapper for CouchApps, web applications served
directly from CouchDB.
</li>
<li>
<b>sstephenson</b>'s <a href="http://github.com/sstephenson/eco">Eco</a>
&mdash; high-performance embedded CoffeeScript templates, after EJS and ERB.
</li>
<li>
<b>mauricemach</b>'s <a href="http://github.com/mauricemach/coffeekup">CoffeeKup</a>
&mdash; Markup as CoffeeScript. After _why's
<a href="http://markaby.github.com/">Markaby</a>.
</li>
<li>
<b>jashkenas</b>' <a href="http://jashkenas.github.com/docco/">Docco</a>
&mdash; a quick-and-dirty literate-programming-style documentation generator
for CoffeeScript. Used to produce the annotated source.
</li>
<li>
<b>naturalethic</b>'s <a href="http://github.com/naturalethic/coffee-mongo">coffee-mongo</a>
&mdash; an asynchronous MongoDB ORM, for use with Node.js and CoffeeScript.
</li>
<li>
<b>mauricemach</b>'s <a href="https://github.com/mauricemach/zappa">Zappa</a>
&mdash; a DSL for building web apps, built on top of Express and Socket.IO.
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
</li>
</ul>
@@ -1090,16 +1020,42 @@ Expressions
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">1.1.1
<span class="timestamp"> &ndash; <small>May 10, 2011</small></span>
</b>
Bugfix release for classes with external constructor functions, see
issue #1182.
</p>
<p>
<b class="header" style="margin-top: 20px;">1.1.0
<span class="timestamp"> &ndash; <small>May 1, 2011</small></span>
</b>
When running via <tt>coffee</tt> executable, <tt>process.argv</tt> and
friends now report <tt>coffee</tt> instead of <tt>node</tt>.
Better compatibility with <b>Node.js 0.4.x</b> module lookup changes.
The output in the REPL is now colorized, like Node's is.
Giving your concatenated CoffeeScripts a name when using <tt>--join</tt> is now mandatory.
Fix for lexing compound division <tt>/=</tt> as a regex accidentally.
All <tt>text/coffeescript</tt> tags should now execute in the order they're included.
Fixed an issue with extended subclasses using external constructor functions.
Fixed an edge-case infinite loop in <tt>addImplicitParentheses</tt>.
Fixed exponential slowdown with long chains of function calls.
Globals no longer leak into the CoffeeScript REPL.
Splatted parameters are declared local to the function.
</p>
<p>
<b class="header" style="margin-top: 20px;">1.0.1
<span class="timestamp"> &ndash; <small>Jan 31, 2011</small></span>
</b>
Fixed a lexer bug with Unicode identifiers. Updated REPL for compatibility
with Node.js 0.3.7. Fixed requiring relative paths in the REPL. Trailing
<tt>return</tt> and <tt>return undefined</tt> are now optimized away.
Stopped requiring the core Node.js <tt>"util"</tt> module for
<tt>return</tt> and <tt>return undefined</tt> are now optimized away.
Stopped requiring the core Node.js <tt>"util"</tt> module for
back-compatibility with Node.js 0.2.5. Fixed a case where a
conditional <tt>return</tt> would cause fallthrough in a <tt>switch</tt>
conditional <tt>return</tt> would cause fallthrough in a <tt>switch</tt>
statement. Optimized empty objects in destructuring assignment.
</p>
@@ -1576,7 +1532,7 @@ Expressions
$('#repl_source').keyup -> compileSource()
# Eval the compiled js.
$('.minibutton.run').click ->
evalJS = ->
try
eval window.compiledJS
catch error then alert error
@@ -1592,6 +1548,8 @@ Expressions
closeMenus = ->
$('.navigation.active').removeClass 'active'
$('.minibutton.run').click evalJS
# Bind navigation buttons to open the menus.
$('.navigation').click (e) ->
return if e.target.tagName.toLowerCase() is 'a'
@@ -1603,9 +1561,15 @@ Expressions
$(this).addClass 'active'
false
$(document.body).click (e) ->
return false if $(e.target).hasClass('minibutton')
closeMenus()
# Dismiss console if Escape pressed or click falls outside console
# Trigger Run button on Ctrl-Enter
$(document.body)
.keydown (e) ->
closeMenus() if e.which == 27
evalJS() if e.which == 13 and (e.metaKey or e.ctrlKey) and $('.minibutton.run:visible').length
.click (e) ->
return false if $(e.target).hasClass('minibutton')
closeMenus()
$('#open_webchat').click ->
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')

View File

@@ -1,4 +1,4 @@
/*
CoffeeScript Compiler v1.0.1
CoffeeScript Compiler v1.1.1
Released under the MIT License
*/

View File

@@ -17,10 +17,10 @@ Animal = (function() {
return Animal;
})();
Snake = (function() {
__extends(Snake, Animal);
function Snake() {
Snake.__super__.constructor.apply(this, arguments);
}
__extends(Snake, Animal);
Snake.prototype.move = function() {
alert("Slithering...");
return Snake.__super__.move.call(this, 5);
@@ -28,10 +28,10 @@ Snake = (function() {
return Snake;
})();
Horse = (function() {
__extends(Horse, Animal);
function Horse() {
Horse.__super__.constructor.apply(this, arguments);
}
__extends(Horse, Animal);
Horse.prototype.move = function() {
alert("Galloping...");
return Horse.__super__.move.call(this, 45);

View File

@@ -1,6 +1,10 @@
var footprints, solipsism;
if ((typeof mind != "undefined" && mind !== null) && !(typeof world != "undefined" && world !== null)) {
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
solipsism = true;
}
typeof speed != "undefined" && speed !== null ? speed : speed = 75;
footprints = typeof yeti != "undefined" && yeti !== null ? yeti : "bear";
if (typeof speed !== "undefined" && speed !== null) {
speed;
} else {
speed = 75;
};
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";

View File

@@ -21,7 +21,7 @@ race = function() {
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
return print(winner, runners);
};
if (typeof elvis != "undefined" && elvis !== null) {
if (typeof elvis !== "undefined" && elvis !== null) {
alert("I knew it!");
}
cubes = (function() {

View File

@@ -1,2 +1,2 @@
var zip, _ref;
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;

File diff suppressed because one or more lines are too long

View File

@@ -58,10 +58,10 @@
<div class="screenshadow bl"></div>
<div class="screenshadow br"></div>
<div id="repl_source_wrap">
<textarea id="repl_source" rows="100">alert "Hello CoffeeScript!"</textarea>
<textarea id="repl_source" rows="100" spellcheck="false">alert "Hello CoffeeScript!"</textarea>
</div>
<div id="repl_results_wrap"><pre id="repl_results"></pre></div>
<div class="minibutton dark run">Run</div>
<div class="minibutton dark run" title="Ctrl-Enter">Run</div>
<br class="clear" />
</div>
</div>
@@ -109,7 +109,7 @@
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.0.1">1.0.1</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.1.1">1.1.1</a>
</p>
<h2>
@@ -170,7 +170,7 @@ math <span class="Keyword">=</span> {
winner <span class="Keyword">=</span> arguments[<span class="Number">0</span>], runners <span class="Keyword">=</span> <span class="Number">2</span> <span class="Keyword">&lt;=</span> arguments.<span class="LibraryConstant">length</span> ? __slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">1</span>) : [];
<span class="Keyword">return</span> <span class="LibraryFunction">print</span>(winner, runners);
};
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> elvis <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>I knew it!<span class="String">&quot;</span></span>);
}
cubes <span class="Keyword">=</span> (<span class="Storage">function</span>() {
@@ -205,7 +205,7 @@ race = function() {
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
return print(winner, runners);
};
if (typeof elvis != "undefined" && elvis !== null) {
if (typeof elvis !== "undefined" && elvis !== null) {
alert("I knew it!");
}
cubes = (function() {
@@ -241,17 +241,21 @@ cubes = (function() {
</p>
<pre>
npm install coffee-script</pre>
npm install -g coffee-script</pre>
<p>
If you'd prefer to install the latest master version of CoffeeScript, you
can clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
<p>
(Leave off the <tt>-g</tt> if you don't wish to install globally.)
</p>
<p>
If you'd prefer to install the latest master version of CoffeeScript, you
can clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
<pre>
sudo bin/cake install</pre>
@@ -294,10 +298,11 @@ sudo bin/cake install</pre>
</td>
</tr>
<tr>
<td><code>-j, --join</code></td>
<td><code>-j, --join [FILE]</code></td>
<td>
Before compiling, concatenate all scripts together in the order they
were passed. Useful for building large projects.
were passed, and write them into the specified file.
Useful for building large projects.
</td>
</tr>
<tr>
@@ -401,7 +406,7 @@ Expressions
</li>
<li>
Concatenate a list of files into a single script:<br />
<tt>coffee -o lib/ --join --compile src/*.coffee</tt>
<tt>coffee --join project.js --compile src/*.coffee</tt>
</li>
<li>
Print out the compiled JS from a one-liner:<br />
@@ -934,7 +939,7 @@ lyrics = (function() {
<b class="header">Array Slicing and Splicing with Ranges</b>
Ranges can also be used to extract slices of arrays.
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
with three docs (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
with three dots (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
</p>
<div class='code'><pre class="idle">numbers <span class="Keyword">=</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
@@ -1201,17 +1206,25 @@ footprints <span class="Keyword">=</span> yeti <span class="Keyword">?</span> <s
</pre><pre class="idle"><span class="Storage">var</span> footprints, solipsism;
<span class="Keyword">if</span> ((<span class="Keyword">typeof</span> mind <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> <span class="Keyword">!</span>(<span class="Keyword">typeof</span> world <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>)) {
<span class="Keyword">if</span> ((<span class="Keyword">typeof</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> <span class="Keyword">!</span>(<span class="Keyword">typeof</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>)) {
solipsism <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
}
<span class="Keyword">typeof</span> speed <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> speed <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span> ? speed : speed <span class="Keyword">=</span> <span class="Number">75</span>;
footprints <span class="Keyword">=</span> <span class="Keyword">typeof</span> yeti <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> yeti <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span> ? yeti : <span class="String"><span class="String">&quot;</span>bear<span class="String">&quot;</span></span>;
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> speed <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> speed <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
speed;
} <span class="Keyword">else</span> {
speed <span class="Keyword">=</span> <span class="Number">75</span>;
};
footprints <span class="Keyword">=</span> <span class="Keyword">typeof</span> yeti <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> yeti <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span> ? yeti : <span class="String"><span class="String">&quot;</span>bear<span class="String">&quot;</span></span>;
</pre><script>window.example21 = "solipsism = true if mind? and not world?\n\nspeed ?= 75\n\nfootprints = yeti ? \"bear\"\n\nalert footprints"</script><div class='minibutton load' onclick='javascript: loadConsole(example21);'>load</div><div class='minibutton ok' onclick='javascript: var footprints, solipsism;
if ((typeof mind != "undefined" && mind !== null) && !(typeof world != "undefined" && world !== null)) {
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
solipsism = true;
}
typeof speed != "undefined" && speed !== null ? speed : speed = 75;
footprints = typeof yeti != "undefined" && yeti !== null ? yeti : "bear";;alert(footprints);'>run: footprints</div><br class='clear' /></div>
if (typeof speed !== "undefined" && speed !== null) {
speed;
} else {
speed = 75;
};
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";;alert(footprints);'>run: footprints</div><br class='clear' /></div>
<p>
The accessor variant of the existential operator <tt>?.</tt> can be used to soak
up null references in a chain of properties. Use it instead
@@ -1222,7 +1235,7 @@ footprints = typeof yeti != "undefined" && yeti !== null ? yeti : "bear";;alert(
</p>
<div class='code'><pre class="idle">zip <span class="Keyword">=</span> lottery.drawWinner<span class="Keyword">?</span>().address<span class="Keyword">?</span>.zipcode
</pre><pre class="idle"><span class="Storage">var</span> zip, _ref;
zip <span class="Keyword">=</span> <span class="Keyword">typeof</span> lottery.drawWinner <span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>function<span class="String">&quot;</span></span> ? (_ref <span class="Keyword">=</span> lottery.drawWinner().address) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="BuiltInConstant">null</span> ? _ref.zipcode : <span class="Storage">void</span> <span class="Number">0</span> : <span class="Storage">void</span> <span class="Number">0</span>;
zip <span class="Keyword">=</span> <span class="Keyword">typeof</span> lottery.drawWinner <span class="Keyword">===</span> <span class="String"><span class="String">&quot;</span>function<span class="String">&quot;</span></span> ? (_ref <span class="Keyword">=</span> lottery.drawWinner().address) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="BuiltInConstant">null</span> ? _ref.zipcode : <span class="Storage">void</span> <span class="Number">0</span> : <span class="Storage">void</span> <span class="Number">0</span>;
</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
@@ -1253,8 +1266,7 @@ zip <span class="Keyword">=</span> <span class="Keyword">typeof</span> lottery.d
in a single assignable expression.
</p>
<p>
Constructor functions are named, to better support reflection. In the
example below for the first class, <tt>this.constructor.name is "Animal"</tt>.
Constructor functions are named, to better support helpful stack traces.
</p>
<div class='code'><pre class="idle"><span class="Storage">class</span> <span class="TypeName">Animal</span>
<span class="FunctionName">constructor</span><span class="Keyword">:</span> <span class="FunctionArgument">(@name)</span> <span class="Storage">-&gt;</span>
@@ -1300,10 +1312,10 @@ Animal <span class="Keyword">=</span> (<span class="Storage">function</span>() {
<span class="Keyword">return</span> Animal;
})();
Snake <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__extends(Snake, Animal);
<span class="Storage">function</span> <span class="FunctionName">Snake</span>() {
Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
}
__extends(Snake, Animal);
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>);
<span class="Keyword">return</span> Snake.__super__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">5</span>);
@@ -1311,10 +1323,10 @@ Snake <span class="Keyword">=</span> (<span class="Storage">function</span>() {
<span class="Keyword">return</span> Snake;
})();
Horse <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__extends(Horse, Animal);
<span class="Storage">function</span> <span class="FunctionName">Horse</span>() {
Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
}
__extends(Horse, Animal);
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>);
<span class="Keyword">return</span> Horse.__super__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">45</span>);
@@ -1344,10 +1356,10 @@ Animal = (function() {
return Animal;
})();
Snake = (function() {
__extends(Snake, Animal);
function Snake() {
Snake.__super__.constructor.apply(this, arguments);
}
__extends(Snake, Animal);
Snake.prototype.move = function() {
alert("Slithering...");
return Snake.__super__.move.call(this, 5);
@@ -1355,10 +1367,10 @@ Snake = (function() {
return Snake;
})();
Horse = (function() {
__extends(Horse, Animal);
function Horse() {
Horse.__super__.constructor.apply(this, arguments);
}
__extends(Horse, Animal);
Horse.prototype.move = function() {
alert("Galloping...");
return Horse.__super__.move.call(this, 45);
@@ -1372,8 +1384,9 @@ tom.move();;'>run</div><br class='clear' /></div>
<p>
If structuring your prototypes classically isn't your cup of tea, CoffeeScript
provides a couple of lower-level conveniences. The <tt>extends</tt> operator
helps with proper prototype setup, <tt>::</tt> gives you
quick access to an object's prototype, and <tt>super()</tt>
helps with proper prototype setup, and can be used to create an inheritance
chain between any pair of constructor functions; <tt>::</tt> gives you
quick access to an object's prototype; and <tt>super()</tt>
is converted into a call against the immediate ancestor's method of the same name.
</p>
<div class='code'><pre class="idle"><span class="FunctionName">String::dasherize </span><span class="Keyword">=</span> <span class="Keyword">-</span><span class="Keyword">&gt;</span>
@@ -1708,20 +1721,20 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
<p>
Sometimes you'd like to pass a block comment through to the generated
JavaScript. For example, when you need to embed a licensing header at
the top of a file. Block comments, which mirror the synax for heredocs,
the top of a file. Block comments, which mirror the syntax for heredocs,
are preserved in the generated code.
</p>
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">###</span></span>
<span class="Comment">CoffeeScript Compiler v1.0.1</span>
<span class="Comment">CoffeeScript Compiler v1.1.1</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">###</span></span>
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
<span class="Comment">CoffeeScript Compiler v1.0.1</span>
<span class="Comment">CoffeeScript Compiler v1.1.1</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">*/</span></span>
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.0.1\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.1.1\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
<p>
<span id="regexes" class="bookmark"></span>
@@ -1831,6 +1844,10 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
</h2>
<ul>
<li>
<b>sstephenson</b>'s <a href="http://pow.cx/">Pow</a>,
a zero-configuration Rack server, with comprehensive annotated source.
</li>
<li>
<b>frank06</b>'s <a href="http://riakjs.org/">riak-js</a>, a Node.js client for
<a href="http://www.basho.com/Riak.html">Riak</a>, with support for HTTP
@@ -1840,6 +1857,10 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
<b>technoweenie</b>'s <a href="https://github.com/technoweenie/coffee-resque">Coffee-Resque</a>,
a port of <a href="https://github.com/defunkt/resque">Resque</a> for Node.js.
</li>
<li>
<b>assaf</b>'s <a href="http://zombie.labnotes.org/">Zombie.js</a>,
A headless, full-stack, faux-browser testing library for Node.js.
</li>
<li>
<b>jashkenas</b>' <a href="documentation/docs/underscore.html">Underscore.coffee</a>, a port
of the <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
@@ -1853,10 +1874,6 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
<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.
</li>
<li>
<b>sstephenson</b>'s <a href="http://sstephenson.github.com/strscan-js/">StringScanner</a>,
a simple tokenizer and lexical scanner for JavaScript strings.
</li>
</ul>
<h2>
@@ -1879,102 +1896,23 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
</li>
<li>
<a href="http://github.com/jashkenas/coffee-script/issues">CoffeeScript Issues</a><br />
Bugs reports, feature requests, and general discussion all belong here.
Bug reports, feature proposals, and ideas for changes to the language belong here.
</li>
<li>
If you'd like to chat, stop by <tt>#coffeescript</tt> on Freenode in the
IRC client of your choice, or on
<a href="http://webchat.freenode.net/">webchat.freenode.net</a>.
<a href="https://groups.google.com/forum/#!forum/coffeescript">CoffeeScript Google Group</a><br />
If you'd like to ask a question, the mailing list is a good place to get help.
</li>
<li>
<b>satyr</b>'s <a href="http://github.com/satyr/coco">Coco</a>
&mdash; An avant-garde dialect of CoffeeScript that frequently pioneers
features and optimizations, some of which CoffeeScript later adopts.
Check out the <a href="https://github.com/satyr/coco/wiki/additions">list of additions</a>
to the language.
<a href="http://github.com/jashkenas/coffee-script/wiki">The CoffeeScript Wiki</a><br />
If you've ever learned a neat CoffeeScript tip or trick, or ran into a gotcha &mdash; share it on the wiki.
The wiki also serves as a directory of handy
<a href="http://github.com/jashkenas/coffee-script/wiki/Text-editor-plugins">text editor extensions</a>,
<a href="http://github.com/jashkenas/coffee-script/wiki/Web-framework-plugins">web framework plugins</a>,
and general <a href="http://github.com/jashkenas/coffee-script/wiki/Build-tools">CoffeeScript build tools</a>.
</li>
<li>
<b>yeungda</b>'s <a href="http://github.com/yeungda/jcoffeescript">JCoffeeScript</a>
&mdash; A Java Library that uses Rhino to compile CoffeeScript, allowing
compilation within Java projects or on systems that Node.js doesn't support.
</li>
<li>
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
&mdash; a Emacs major mode that provides syntax highlighting, indentation
support, and some bonus commands.
</li>
<li>
<b>jashkenas</b>' <a href="http://github.com/jashkenas/coffee-script-tmbundle">CoffeeScript TextMate Bundle</a>
&mdash; which provides syntax highlighting, snippet expansion, and the
ability to run bits of CoffeeScript from within TextMate itself.
</li>
<li>
<b>kchmck</b>'s <a href="http://github.com/kchmck/vim-coffee-script">Vim CoffeeScript</a>
&mdash; which adds Vim syntax highlighting and indentation support.
</li>
<li>
<b>wavded</b>'s <a href="http://github.com/wavded/gedit-coffeescript">gedit-coffeescript</a>
&mdash; a CoffeeScript syntax highlighter for the gedit text editor.
</li>
<li>
<b>yeungda</b>'s <a href="http://yeungda.github.com/coffeescript-idea/">coffeescript-idea</a>
&mdash; a plugin for IntelliJ IDEA and RubyMine providing syntax highlighting.
</li>
<li>
<b>dhotson</b>'s <a href="https://github.com/dhotson/coffeescript-jedit">coffeescript-jedit</a>
&mdash; which provides syntax highlighting support in jEdit.
</li>
<li>
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
&mdash; a small Rack middleware for serving CoffeeScript files as
compiled JavaScript on the fly.
</li>
<li>
<b>jnicklas</b>'s <a href="http://github.com/jnicklas/bistro_car">BistroCar</a>
&mdash; a plugin that serves and bundles CoffeeScript from within your
Rails application.
</li>
<li>
<b>dsc</b>'s <a href="http://github.com/dsc/coffeecup">CoffeeCup</a>
&mdash; a Python WSGI middleware that compiles CoffeeScript to JavaScript
on-demand during development.
</li>
<li>
<b>sutto</b>'s <a href="http://github.com/Sutto/barista">Barista</a>
&mdash; a BistroCar alternative that integrates well with
<a href="http://documentcloud.github.com/jammit">Jammit</a> and Rails 3.
</li>
<li>
<b>inem</b> and <b>gerad</b>'s <a href="http://github.com/gerad/coffee-haml-filter">coffee-haml-filter</a>
&mdash; a custom filter for rendering CoffeeScript inline within
<a href="http://haml-lang.com/">HAML</a> templates.
</li>
<li>
<b>andrzejsliwa</b>'s <a href="http://github.com/andrzejsliwa/coffeeapp">CoffeeApp</a>
&mdash; a CoffeeScript wrapper for CouchApps, web applications served
directly from CouchDB.
</li>
<li>
<b>sstephenson</b>'s <a href="http://github.com/sstephenson/eco">Eco</a>
&mdash; high-performance embedded CoffeeScript templates, after EJS and ERB.
</li>
<li>
<b>mauricemach</b>'s <a href="http://github.com/mauricemach/coffeekup">CoffeeKup</a>
&mdash; Markup as CoffeeScript. After _why's
<a href="http://markaby.github.com/">Markaby</a>.
</li>
<li>
<b>jashkenas</b>' <a href="http://jashkenas.github.com/docco/">Docco</a>
&mdash; a quick-and-dirty literate-programming-style documentation generator
for CoffeeScript. Used to produce the annotated source.
</li>
<li>
<b>naturalethic</b>'s <a href="http://github.com/naturalethic/coffee-mongo">coffee-mongo</a>
&mdash; an asynchronous MongoDB ORM, for use with Node.js and CoffeeScript.
</li>
<li>
<b>mauricemach</b>'s <a href="https://github.com/mauricemach/zappa">Zappa</a>
&mdash; a DSL for building web apps, built on top of Express and Socket.IO.
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
</li>
</ul>
@@ -1998,16 +1936,42 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">1.1.1
<span class="timestamp"> &ndash; <small>May 10, 2011</small></span>
</b>
Bugfix release for classes with external constructor functions, see
issue #1182.
</p>
<p>
<b class="header" style="margin-top: 20px;">1.1.0
<span class="timestamp"> &ndash; <small>May 1, 2011</small></span>
</b>
When running via <tt>coffee</tt> executable, <tt>process.argv</tt> and
friends now report <tt>coffee</tt> instead of <tt>node</tt>.
Better compatibility with <b>Node.js 0.4.x</b> module lookup changes.
The output in the REPL is now colorized, like Node's is.
Giving your concatenated CoffeeScripts a name when using <tt>--join</tt> is now mandatory.
Fix for lexing compound division <tt>/=</tt> as a regex accidentally.
All <tt>text/coffeescript</tt> tags should now execute in the order they're included.
Fixed an issue with extended subclasses using external constructor functions.
Fixed an edge-case infinite loop in <tt>addImplicitParentheses</tt>.
Fixed exponential slowdown with long chains of function calls.
Globals no longer leak into the CoffeeScript REPL.
Splatted parameters are declared local to the function.
</p>
<p>
<b class="header" style="margin-top: 20px;">1.0.1
<span class="timestamp"> &ndash; <small>Jan 31, 2011</small></span>
</b>
Fixed a lexer bug with Unicode identifiers. Updated REPL for compatibility
with Node.js 0.3.7. Fixed requiring relative paths in the REPL. Trailing
<tt>return</tt> and <tt>return undefined</tt> are now optimized away.
Stopped requiring the core Node.js <tt>"util"</tt> module for
<tt>return</tt> and <tt>return undefined</tt> are now optimized away.
Stopped requiring the core Node.js <tt>"util"</tt> module for
back-compatibility with Node.js 0.2.5. Fixed a case where a
conditional <tt>return</tt> would cause fallthrough in a <tt>switch</tt>
conditional <tt>return</tt> would cause fallthrough in a <tt>switch</tt>
statement. Optimized empty objects in destructuring assignment.
</p>
@@ -2484,7 +2448,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
$('#repl_source').keyup -> compileSource()
# Eval the compiled js.
$('.minibutton.run').click ->
evalJS = ->
try
eval window.compiledJS
catch error then alert error
@@ -2500,6 +2464,8 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
closeMenus = ->
$('.navigation.active').removeClass 'active'
$('.minibutton.run').click evalJS
# Bind navigation buttons to open the menus.
$('.navigation').click (e) ->
return if e.target.tagName.toLowerCase() is 'a'
@@ -2511,9 +2477,15 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
$(this).addClass 'active'
false
$(document.body).click (e) ->
return false if $(e.target).hasClass('minibutton')
closeMenus()
# Dismiss console if Escape pressed or click falls outside console
# Trigger Run button on Ctrl-Enter
$(document.body)
.keydown (e) ->
closeMenus() if e.which == 27
evalJS() if e.which == 13 and (e.metaKey or e.ctrlKey) and $('.minibutton.run:visible').length
.click (e) ->
return false if $(e.target).hasClass('minibutton')
closeMenus()
$('#open_webchat').click ->
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')

View File

@@ -12,10 +12,10 @@
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
};
if (typeof window == "undefined" || window === null) {
if (typeof window === "undefined" || window === null) {
return;
}
CoffeeScript.load = function(url, options) {
CoffeeScript.load = function(url, callback) {
var xhr;
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
@@ -23,25 +23,48 @@
xhr.overrideMimeType('text/plain');
}
xhr.onreadystatechange = function() {
var _ref;
if (xhr.readyState === 4) {
return CoffeeScript.run(xhr.responseText, options);
if ((_ref = xhr.status) === 0 || _ref === 200) {
CoffeeScript.run(xhr.responseText);
} else {
throw new Error("Could not load " + url);
}
if (callback) {
return callback();
}
}
};
return xhr.send(null);
};
runScripts = function() {
var script, _i, _len, _ref;
_ref = document.getElementsByTagName('script');
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
script = _ref[_i];
if (script.type === 'text/coffeescript') {
if (script.src) {
CoffeeScript.load(script.src);
} else {
CoffeeScript.run(script.innerHTML);
var coffees, execute, index, length, s, scripts;
scripts = document.getElementsByTagName('script');
coffees = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
s = scripts[_i];
if (s.type === 'text/coffeescript') {
_results.push(s);
}
}
}
return _results;
})();
index = 0;
length = coffees.length;
(execute = function() {
var script;
script = coffees[index++];
if ((script != null ? script.type : void 0) === 'text/coffeescript') {
if (script.src) {
return CoffeeScript.load(script.src, execute);
} else {
CoffeeScript.run(script.innerHTML);
return execute();
}
}
})();
return null;
};
if (window.addEventListener) {

View File

@@ -1,13 +1,16 @@
(function() {
var Lexer, RESERVED, compile, fs, lexer, parser, path, _ref;
var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref;
fs = require('fs');
path = require('path');
vm = require('vm');
_ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
parser = require('./parser').parser;
if (require.extensions) {
require.extensions['.coffee'] = function(module, filename) {
var content;
content = compile(fs.readFileSync(filename, 'utf8'));
content = compile(fs.readFileSync(filename, 'utf8'), {
filename: filename
});
return module._compile(content, filename);
};
} else if (require.registerExtension) {
@@ -15,7 +18,7 @@
return compile(content);
});
}
exports.VERSION = '1.0.1';
exports.VERSION = '1.1.1';
exports.RESERVED = RESERVED;
exports.helpers = require('./helpers');
exports.compile = compile = function(code, options) {
@@ -42,15 +45,19 @@
}
};
exports.run = function(code, options) {
var root;
var Module, root;
root = module;
while (root.parent) {
root = root.parent;
}
root.filename = options.filename ? fs.realpathSync(options.filename) : '.';
root.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
if (root.moduleCache) {
root.moduleCache = {};
}
if (process.binding('natives').module) {
Module = require('module').Module;
root.paths = Module._nodeModulePaths(path.dirname(options.filename));
}
if (path.extname(root.filename) !== '.coffee' || require.extensions) {
return root._compile(compile(code, options), root.filename);
} else {
@@ -58,16 +65,34 @@
}
};
exports.eval = function(code, options) {
var __dirname, __filename;
__filename = module.filename = options.filename;
__dirname = path.dirname(__filename);
return eval(compile(code, options));
var g, js, sandbox;
if (options == null) {
options = {};
}
sandbox = options.sandbox;
if (!sandbox) {
sandbox = {
require: require,
module: {
exports: {}
}
};
for (g in global) {
sandbox[g] = global[g];
}
sandbox.global = sandbox;
sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox;
}
sandbox.__filename = options.filename || 'eval';
sandbox.__dirname = path.dirname(sandbox.__filename);
js = compile("_=(" + (code.trim()) + ")", options);
return vm.runInNewContext(js, sandbox, sandbox.__filename);
};
lexer = new Lexer;
parser.lexer = {
lex: function() {
var tag, _ref;
_ref = this.tokens[this.pos++] || [''], tag = _ref[0], this.yytext = _ref[1], this.yylineno = _ref[2];
var tag, _ref2;
_ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
return tag;
},
setInput: function(tokens) {

View File

@@ -15,7 +15,7 @@
return process.binding('stdio').writeError(line + '\n');
};
BANNER = 'Usage: coffee [options] path/to/script.coffee';
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join [FILE]', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
opts = {};
sources = [];
contents = [];
@@ -50,6 +50,8 @@
opts.literals = sources.splice(1).concat(opts.literals);
}
process.ARGV = process.argv = process.argv.slice(0, 2).concat(opts.literals);
process.argv[0] = 'coffee';
process.execPath = require.main.filename;
return compileScripts();
};
compileScripts = function() {
@@ -64,21 +66,24 @@
throw new Error("File not found: " + source);
}
return fs.stat(source, function(err, stats) {
if (err) {
throw err;
}
if (stats.isDirectory()) {
return fs.readdir(source, function(err, files) {
var file, _i, _len, _results;
_results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
_results.push(compile(path.join(source, file)));
var file, _j, _len2, _results2;
_results2 = [];
for (_j = 0, _len2 = files.length; _j < _len2; _j++) {
file = files[_j];
_results2.push(compile(path.join(source, file)));
}
return _results;
return _results2;
});
} else if (topLevel || path.extname(source) === '.coffee') {
fs.readFile(source, function(err, code) {
if (opts.join) {
contents[sources.indexOf(source)] = code.toString();
if (helpers.compact(contents).length === sources.length) {
if (helpers.compact(contents).length > 0) {
return compileJoin();
}
} else {
@@ -152,15 +157,15 @@
compileJoin = function() {
var code;
code = contents.join('\n');
return compileScript("concatenation", code, "concatenation");
return compileScript(opts.join, code, opts.join);
};
loadRequires = function() {
var realFilename, req, _i, _len, _ref;
var realFilename, req, _i, _len, _ref2;
realFilename = module.filename;
module.filename = '.';
_ref = opts.require;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
req = _ref[_i];
_ref2 = opts.require;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
req = _ref2[_i];
require(req);
}
return module.filename = realFilename;
@@ -196,7 +201,7 @@
if (err) {
return printLine(err.message);
} else if (opts.compile && opts.watch) {
return console.log("" + ((new Date).toTimeString()) + " - compiled " + source);
return console.log("" + ((new Date).toLocaleTimeString()) + " - compiled " + source);
}
});
};
@@ -223,11 +228,11 @@
printTokens = function(tokens) {
var strings, tag, token, value;
strings = (function() {
var _i, _len, _ref, _results;
var _i, _len, _ref2, _results;
_results = [];
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
token = tokens[_i];
_ref = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref[0], value = _ref[1];
_ref2 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref2[0], value = _ref2[1];
_results.push("[" + tag + " " + value + "]");
}
return _results;

View File

@@ -169,13 +169,11 @@
return new Access($2, 'proto');
}), o('::', function() {
return new Access(new Literal('prototype'));
}), o('Index'), o('Slice', function() {
return new Slice($1);
})
}), o('Index')
],
Index: [
o('INDEX_START Expression INDEX_END', function() {
return new Index($2);
o('INDEX_START IndexValue INDEX_END', function() {
return $2;
}), o('INDEX_SOAK Index', function() {
return extend($2, {
soak: true
@@ -186,6 +184,13 @@
});
})
],
IndexValue: [
o('Expression', function() {
return new Index($1);
}), o('Slice', function() {
return new Slice($1);
})
],
Object: [
o('{ AssignList OptComma }', function() {
return new Obj($2, $1.generated);
@@ -280,12 +285,12 @@
})
],
Slice: [
o('INDEX_START Expression RangeDots Expression INDEX_END', function() {
return new Range($2, $4, $3);
}), o('INDEX_START Expression RangeDots INDEX_END', function() {
return new Range($2, null, $3);
}), o('INDEX_START RangeDots Expression INDEX_END', function() {
return new Range(null, $3, $2);
o('Expression RangeDots Expression', function() {
return new Range($1, $3, $2);
}), o('Expression RangeDots', function() {
return new Range($1, null, $2);
}), o('RangeDots Expression', function() {
return new Range(null, $2, $1);
})
],
ArgList: [

View File

@@ -1,5 +1,5 @@
(function() {
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, last, op, starts, _ref;
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
@@ -37,7 +37,7 @@
return (new Rewriter).rewrite(this.tokens);
};
Lexer.prototype.identifierToken = function() {
var colon, forcedIdentifier, id, input, match, prev, tag, _ref, _ref2;
var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return 0;
}
@@ -46,11 +46,11 @@
this.token('OWN', id);
return id.length;
}
forcedIdentifier = colon || (prev = last(this.tokens)) && !prev.spaced && ((_ref = prev[0]) === '.' || _ref === '?.' || _ref === '@' || _ref === '::');
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
tag = 'IDENTIFIER';
if (__indexOf.call(JS_KEYWORDS, id) >= 0 || !forcedIdentifier && __indexOf.call(COFFEE_KEYWORDS, id) >= 0) {
tag = id.toUpperCase();
if (tag === 'WHEN' && (_ref2 = this.tag(), __indexOf.call(LINE_BREAK, _ref2) >= 0)) {
if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
tag = 'LEADING_WHEN';
} else if (tag === 'FOR') {
this.seenFor = true;
@@ -81,8 +81,8 @@
}
}
if (!forcedIdentifier) {
if (COFFEE_ALIASES.hasOwnProperty(id)) {
id = COFFEE_ALIASES[id];
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
id = COFFEE_ALIAS_MAP[id];
}
tag = (function() {
switch (id) {
@@ -175,7 +175,6 @@
return 0;
}
comment = match[0], here = match[1];
this.line += count(comment, '\n');
if (here) {
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
herecomment: true,
@@ -183,6 +182,7 @@
}));
this.token('TERMINATOR', '\n');
}
this.line += count(comment, '\n');
return comment.length;
};
Lexer.prototype.jsToken = function() {
@@ -194,7 +194,7 @@
return script.length;
};
Lexer.prototype.regexToken = function() {
var match, prev, regex, _ref;
var match, prev, regex, _ref2;
if (this.chunk.charAt(0) !== '/') {
return 0;
}
@@ -202,7 +202,7 @@
return this.heregexToken(match);
}
prev = last(this.tokens);
if (prev && (_ref = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref) >= 0)) {
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
return 0;
}
if (!(match = REGEX.exec(this.chunk))) {
@@ -213,7 +213,7 @@
return regex.length;
};
Lexer.prototype.heregexToken = function(match) {
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref, _ref2, _ref3, _ref4;
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
heregex = match[0], body = match[1], flags = match[2];
if (0 > body.indexOf('#{')) {
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
@@ -223,11 +223,11 @@
this.token('IDENTIFIER', 'RegExp');
this.tokens.push(['CALL_START', '(']);
tokens = [];
_ref = this.interpolateString(body, {
_ref2 = this.interpolateString(body, {
regex: true
});
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
_ref2 = _ref[_i], tag = _ref2[0], value = _ref2[1];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
_ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
if (tag === 'TOKENS') {
tokens.push.apply(tokens, value);
} else {
@@ -240,10 +240,10 @@
tokens.push(['+', '+']);
}
tokens.pop();
if (((_ref3 = tokens[0]) != null ? _ref3[0] : void 0) !== 'STRING') {
if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
this.tokens.push(['STRING', '""'], ['+', '+']);
}
(_ref4 = this.tokens).push.apply(_ref4, tokens);
(_ref5 = this.tokens).push.apply(_ref5, tokens);
if (flags) {
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
}
@@ -340,7 +340,7 @@
return this;
};
Lexer.prototype.literalToken = function() {
var match, prev, tag, value, _ref, _ref2, _ref3, _ref4;
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
if (match = OPERATOR.exec(this.chunk)) {
value = match[0];
if (CODE.test(value)) {
@@ -352,10 +352,10 @@
tag = value;
prev = last(this.tokens);
if (value === '=' && prev) {
if (!prev[1].reserved && (_ref = prev[1], __indexOf.call(JS_FORBIDDEN, _ref) >= 0)) {
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
this.assignmentError();
}
if ((_ref2 = prev[1]) === '||' || _ref2 === '&&') {
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
prev[0] = 'COMPOUND_ASSIGN';
prev[1] += '=';
return value.length;
@@ -376,12 +376,12 @@
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
tag = 'LOGIC';
} else if (prev && !prev.spaced) {
if (value === '(' && (_ref3 = prev[0], __indexOf.call(CALLABLE, _ref3) >= 0)) {
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
tag = 'CALL_START';
} else if (value === '[' && (_ref4 = prev[0], __indexOf.call(INDEXABLE, _ref4) >= 0)) {
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
tag = 'INDEX_START';
switch (prev[0]) {
case '?':
@@ -396,15 +396,19 @@
return value.length;
};
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
var attempt, herecomment, indent, match, _ref;
var attempt, herecomment, indent, match, _ref2;
indent = options.indent, herecomment = options.herecomment;
if (herecomment && 0 > doc.indexOf('\n')) {
return doc;
}
if (!herecomment) {
if (herecomment) {
if (HEREDOC_ILLEGAL.test(doc)) {
throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
}
if (doc.indexOf('\n') <= 0) {
return doc;
}
} else {
while (match = HEREDOC_INDENT.exec(doc)) {
attempt = match[1];
if (indent === null || (0 < (_ref = attempt.length) && _ref < indent.length)) {
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
indent = attempt;
}
}
@@ -435,7 +439,7 @@
case 'CALL_START':
if (stack.length) {
stack.pop();
} else {
} else if (tok[0] === '(') {
tok[0] = 'PARAM_START';
return this;
}
@@ -453,9 +457,9 @@
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
};
Lexer.prototype.balancedString = function(str, end) {
var i, letter, prev, stack, _ref;
var i, letter, prev, stack, _ref2;
stack = [end];
for (i = 1, _ref = str.length; (1 <= _ref ? i < _ref : i > _ref); (1 <= _ref ? i += 1 : i -= 1)) {
for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
switch (letter = str.charAt(i)) {
case '\\':
i++;
@@ -480,7 +484,7 @@
throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
};
Lexer.prototype.interpolateString = function(str, options) {
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref, _ref2, _ref3;
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
if (options == null) {
options = {};
}
@@ -506,7 +510,7 @@
rewrite: false
});
nested.pop();
if (((_ref = nested[0]) != null ? _ref[0] : void 0) === 'TERMINATOR') {
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
nested.shift();
}
if (len = nested.length) {
@@ -536,12 +540,12 @@
this.token('(', '(');
}
for (i = 0, _len = tokens.length; i < _len; i++) {
_ref2 = tokens[i], tag = _ref2[0], value = _ref2[1];
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
if (i) {
this.token('+', '+');
}
if (tag === 'TOKENS') {
(_ref3 = this.tokens).push.apply(_ref3, value);
(_ref4 = this.tokens).push.apply(_ref4, value);
} else {
this.token('STRING', this.makeString(value, '"', heredoc));
}
@@ -587,7 +591,7 @@
})();
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
for (op in COFFEE_ALIASES = {
COFFEE_ALIAS_MAP = {
and: '&&',
or: '||',
is: '==',
@@ -597,9 +601,16 @@
no: 'false',
on: 'true',
off: 'false'
}) {
COFFEE_KEYWORDS.push(op);
}
};
COFFEE_ALIASES = (function() {
var _results;
_results = [];
for (key in COFFEE_ALIAS_MAP) {
_results.push(key);
}
return _results;
})();
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
@@ -613,13 +624,14 @@
MULTI_DENT = /^(?:\n[^\n\S]*)+/;
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
REGEX = /^\/(?!\s)[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
HEREGEX_OMIT = /\s+(?:#.*)?/g;
MULTILINER = /\n/g;
HEREDOC_INDENT = /\n+([^\n\S]*)/g;
HEREDOC_ILLEGAL = /\*\//;
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
LINE_CONTINUER = /^\s*(?:,|\??\.(?!\.)|::)/;
LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
TRAILING_SPACES = /\s+$/;
NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,42 +1,109 @@
(function() {
var CoffeeScript, error, helpers, readline, repl, run, stdin, stdout;
var ACCESSOR, CoffeeScript, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, getPropertyNames, inspect, readline, repl, run, stdin, stdout;
var __hasProp = Object.prototype.hasOwnProperty;
CoffeeScript = require('./coffee-script');
helpers = require('./helpers');
readline = require('readline');
inspect = require('util').inspect;
Script = require('vm').Script;
enableColours = false;
if (process.platform !== 'win32') {
enableColours = !process.env.NODE_DISABLE_COLORS;
}
stdin = process.openStdin();
stdout = process.stdout;
error = function(err) {
return stdout.write((err.stack || err.toString()) + '\n\n');
};
helpers.extend(global, {
quit: function() {
return process.exit(0);
}
});
run = function(buffer) {
var val;
try {
val = CoffeeScript.eval(buffer.toString(), {
bare: true,
globals: true,
filename: 'repl'
});
if (val !== void 0) {
process.stdout.write(val + '\n');
backlog = '';
run = (function() {
var g, sandbox;
sandbox = {
require: require,
module: {
exports: {}
}
} catch (err) {
error(err);
};
for (g in global) {
sandbox[g] = global[g];
}
return repl.prompt();
sandbox.global = sandbox;
sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox;
return function(buffer) {
var code, val;
code = backlog += '\n' + buffer.toString();
if (code[code.length - 1] === '\\') {
return backlog = backlog.slice(0, backlog.length - 1);
}
backlog = '';
try {
val = CoffeeScript.eval(code, {
sandbox: sandbox,
bare: true,
filename: 'repl'
});
if (val !== void 0) {
process.stdout.write(inspect(val, false, 2, enableColours) + '\n');
}
} catch (err) {
error(err);
}
return repl.prompt();
};
})();
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
SIMPLEVAR = /\s*(\w*)$/i;
autocomplete = function(text) {
return completeAttribute(text) || completeVariable(text) || [[], text];
};
completeAttribute = function(text) {
var all, completions, match, obj, prefix, val;
if (match = text.match(ACCESSOR)) {
all = match[0], obj = match[1], prefix = match[2];
try {
val = Script.runInThisContext(obj);
} catch (error) {
return [[], text];
}
completions = getCompletions(prefix, getPropertyNames(val));
return [completions, prefix];
}
};
completeVariable = function(text) {
var completions, free, scope, _ref;
if (free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0) {
scope = Script.runInThisContext('this');
completions = getCompletions(free, CoffeeScript.RESERVED.concat(getPropertyNames(scope)));
return [completions, free];
}
};
getCompletions = function(prefix, candidates) {
var el, _i, _len, _results;
_results = [];
for (_i = 0, _len = candidates.length; _i < _len; _i++) {
el = candidates[_i];
if (el.indexOf(prefix) === 0) {
_results.push(el);
}
}
return _results;
};
getPropertyNames = function(obj) {
var name, _results;
_results = [];
for (name in obj) {
if (!__hasProp.call(obj, name)) continue;
_results.push(name);
}
return _results;
};
process.on('uncaughtException', error);
if (readline.createInterface.length < 3) {
repl = readline.createInterface(stdin);
repl = readline.createInterface(stdin, autocomplete);
stdin.on('data', function(buffer) {
return repl.write(buffer);
});
} else {
repl = readline.createInterface(stdin, stdout);
repl = readline.createInterface(stdin, stdout, autocomplete);
}
repl.setPrompt('coffee> ');
repl.on('close', function() {

View File

@@ -121,7 +121,10 @@
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
};
action = function(token, i) {
return this.tokens.splice(i, 0, ['}', '}', token[2]]);
var tok;
tok = ['}', '}', token[2]];
tok.generated = true;
return this.tokens.splice(i, 0, tok);
};
return this.scanTokens(function(token, i, tokens) {
var ago, idx, tag, tok, value, _ref, _ref2;
@@ -173,12 +176,15 @@
if (prev && !prev.spaced && tag === '?') {
token.call = true;
}
if (token.fromThen) {
return 1;
}
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
return 1;
}
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
this.detectEnd(i + 1, function(token, i) {
var post, _ref;
var post, _ref4;
tag = token[0];
if (!seenSingle && token.fromThen) {
return true;
@@ -189,7 +195,7 @@
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
return true;
}
return !token.generated && this.tag(i - 1) !== ',' && __indexOf.call(IMPLICIT_END, tag) >= 0 && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
return !token.generated && this.tag(i - 1) !== ',' && __indexOf.call(IMPLICIT_END, tag) >= 0 && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
}, action);
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
@@ -222,8 +228,8 @@
indent.generated = outdent.generated = true;
tokens.splice(i + 1, 0, indent);
condition = function(token, i) {
var _ref;
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
var _ref3;
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
};
action = function(token, i) {
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);

View File

@@ -46,12 +46,12 @@
return this.add(name, 'param');
};
Scope.prototype.check = function(name, immediate) {
var found, _ref;
var found, _ref2;
found = !!this.type(name);
if (found || immediate) {
return found;
}
return !!((_ref = this.parent) != null ? _ref.check(name) : void 0);
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
};
Scope.prototype.temporary = function(name, index) {
if (name.length > 1) {
@@ -61,10 +61,10 @@
}
};
Scope.prototype.type = function(name) {
var v, _i, _len, _ref;
_ref = this.variables;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
var v, _i, _len, _ref2;
_ref2 = this.variables;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.name === name) {
return v.type;
}
@@ -74,7 +74,7 @@
Scope.prototype.freeVariable = function(type) {
var index, temp;
index = 0;
while (this.check((temp = this.temporary(type, index)), true)) {
while (this.check((temp = this.temporary(type, index)))) {
index++;
}
this.add(temp, 'var', true);
@@ -91,12 +91,12 @@
return !!this.declaredVariables().length;
};
Scope.prototype.declaredVariables = function() {
var realVars, tempVars, v, _i, _len, _ref;
var realVars, tempVars, v, _i, _len, _ref2;
realVars = [];
tempVars = [];
_ref = this.variables;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
_ref2 = this.variables;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type === 'var') {
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
}
@@ -104,11 +104,11 @@
return realVars.sort().concat(tempVars.sort());
};
Scope.prototype.assignedVariables = function() {
var v, _i, _len, _ref, _results;
_ref = this.variables;
var v, _i, _len, _ref2, _results;
_ref2 = this.variables;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type.assigned) {
_results.push("" + v.name + " = " + v.type.value);
}

View File

@@ -1,22 +1,27 @@
{
"name": "coffee-script",
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language", "coffeescript", "compiler"],
"author": "Jeremy Ashkenas",
"version": "1.0.1",
"licenses": [{
"type": "MIT",
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
}],
"engines": {
"node": ">=0.2.5"
},
"directories" : {
"lib" : "./lib"
},
"main" : "./lib/coffee-script",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"
}
"name": "coffee-script",
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language", "coffeescript", "compiler"],
"author": "Jeremy Ashkenas",
"version": "1.1.1",
"licenses": [{
"type": "MIT",
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
}],
"engines": {
"node": ">=0.2.5"
},
"directories" : {
"lib" : "./lib"
},
"main" : "./lib/coffee-script",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"
},
"homepage": "http://coffeescript.org",
"repository": {
"type": "git",
"url": "git://github.com/jashkenas/coffee-script.git"
}
}

View File

@@ -16,24 +16,35 @@ CoffeeScript.run = (code, options = {}) ->
return unless window?
# Load a remote script from the current domain via XHR.
CoffeeScript.load = (url, options) ->
CoffeeScript.load = (url, callback) ->
xhr = new (window.ActiveXObject or XMLHttpRequest)('Microsoft.XMLHTTP')
xhr.open 'GET', url, true
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
xhr.onreadystatechange = ->
CoffeeScript.run xhr.responseText, options if xhr.readyState is 4
if xhr.readyState is 4
if xhr.status in [0, 200]
CoffeeScript.run xhr.responseText
else
throw new Error "Could not load #{url}"
callback() if callback
xhr.send null
# Activate CoffeeScript in the browser by having it compile and evaluate
# all script tags with a content-type of `text/coffeescript`.
# This happens on page load.
runScripts = ->
for script in document.getElementsByTagName 'script'
if script.type is 'text/coffeescript'
scripts = document.getElementsByTagName 'script'
coffees = (s for s in scripts when s.type is 'text/coffeescript')
index = 0
length = coffees.length
do execute = ->
script = coffees[index++]
if script?.type is 'text/coffeescript'
if script.src
CoffeeScript.load script.src
CoffeeScript.load script.src, execute
else
CoffeeScript.run script.innerHTML
execute()
null
# Listen for window load, both in browsers and in IE.

View File

@@ -8,19 +8,20 @@
fs = require 'fs'
path = require 'path'
vm = require 'vm'
{Lexer,RESERVED} = require './lexer'
{parser} = require './parser'
# TODO: Remove registerExtension when fully deprecated.
if require.extensions
require.extensions['.coffee'] = (module, filename) ->
content = compile fs.readFileSync filename, 'utf8'
content = compile fs.readFileSync(filename, 'utf8'), {filename}
module._compile content, filename
else if require.registerExtension
require.registerExtension '.coffee', (content) -> compile content
# The current CoffeeScript version number.
exports.VERSION = '1.0.1'
exports.VERSION = '1.1.1'
# Words that cannot be used as identifiers in CoffeeScript code
exports.RESERVED = RESERVED
@@ -57,10 +58,19 @@ exports.run = (code, options) ->
root = module
while root.parent
root = root.parent
# Set the filename.
root.filename = if options.filename then fs.realpathSync(options.filename) else '.'
root.filename = process.argv[1] =
if options.filename then fs.realpathSync(options.filename) else '.'
# Clear the module cache.
root.moduleCache = {} if root.moduleCache
# Assign paths for node_modules loading
if process.binding('natives').module
{Module} = require 'module'
root.paths = Module._nodeModulePaths path.dirname options.filename
# Compile.
if path.extname(root.filename) isnt '.coffee' or require.extensions
root._compile compile(code, options), root.filename
@@ -69,10 +79,19 @@ exports.run = (code, options) ->
# Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
# The CoffeeScript REPL uses this to run the input.
exports.eval = (code, options) ->
__filename = module.filename = options.filename
__dirname = path.dirname __filename
eval compile code, options
exports.eval = (code, options = {}) ->
sandbox = options.sandbox
unless sandbox
sandbox =
require: require
module : { exports: {} }
sandbox[g] = global[g] for g of global
sandbox.global = sandbox
sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox
sandbox.__filename = options.filename || 'eval'
sandbox.__dirname = path.dirname sandbox.__filename
js = compile "_=(#{code.trim()})", options
vm.runInNewContext js, sandbox, sandbox.__filename
# Instantiate a Lexer for our use here.
lexer = new Lexer

View File

@@ -1,6 +1,6 @@
# The `coffee` utility. Handles command-line compilation of CoffeeScript
# into various forms: saved into `.js` files or printed to stdout, piped to
# [JSLint](http://javascriptlint.com/) or recompiled every time the source is
# [JavaScript Lint](http://javascriptlint.com/) or recompiled every time the source is
# saved, printed as a token stream or as the syntax tree, or launch an
# interactive REPL.
@@ -29,10 +29,10 @@ SWITCHES = [
['-c', '--compile', 'compile to JavaScript and save as .js files']
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-o', '--output [DIR]', 'set the directory for compiled JavaScript']
['-j', '--join', 'concatenate the scripts before compiling']
['-j', '--join [FILE]', 'concatenate the scripts before compiling']
['-w', '--watch', 'watch scripts for changes, and recompile']
['-p', '--print', 'print the compiled JavaScript to stdout']
['-l', '--lint', 'pipe the compiled JavaScript through JSLint']
['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint']
['-s', '--stdio', 'listen for and compile scripts over stdio']
['-e', '--eval', 'compile a string from the command line']
['-r', '--require [FILE*]', 'require a library before executing your script']
@@ -66,6 +66,8 @@ exports.run = ->
if opts.run
opts.literals = sources.splice(1).concat opts.literals
process.ARGV = process.argv = process.argv.slice(0, 2).concat opts.literals
process.argv[0] = 'coffee'
process.execPath = require.main.filename
compileScripts()
# Asynchronously read in each CoffeeScript in a list of source files and
@@ -78,6 +80,7 @@ compileScripts = ->
path.exists source, (exists) ->
throw new Error "File not found: #{source}" if topLevel and not exists
fs.stat source, (err, stats) ->
throw err if err
if stats.isDirectory()
fs.readdir source, (err, files) ->
for file in files
@@ -86,7 +89,7 @@ compileScripts = ->
fs.readFile source, (err, code) ->
if opts.join
contents[sources.indexOf source] = code.toString()
compileJoin() if helpers.compact(contents).length is sources.length
compileJoin() if helpers.compact(contents).length > 0
else
compileScript(source, code.toString(), base)
watch source, base if opts.watch and not opts.join
@@ -131,7 +134,7 @@ compileStdio = ->
# them together.
compileJoin = ->
code = contents.join '\n'
compileScript "concatenation", code, "concatenation"
compileScript opts.join, code, opts.join
# Load files that are to-be-required before compilation occurs.
loadRequires = ->
@@ -165,7 +168,7 @@ writeJs = (source, js, base) ->
if err
printLine err.message
else if opts.compile and opts.watch
console.log "#{(new Date).toTimeString()} - compiled #{source}"
console.log "#{(new Date).toLocaleTimeString()} - compiled #{source}"
path.exists dir, (exists) ->
if exists then compile() else exec "mkdir -p #{dir}", compile

View File

@@ -246,15 +246,19 @@ grammar =
o ':: Identifier', -> new Access $2, 'proto'
o '::', -> new Access new Literal 'prototype'
o 'Index'
o 'Slice', -> new Slice $1
]
# Indexing into an object or array using bracket notation.
Index: [
o 'INDEX_START Expression INDEX_END', -> new Index $2
o 'INDEX_START IndexValue INDEX_END', -> $2
o 'INDEX_SOAK Index', -> extend $2, soak : yes
o 'INDEX_PROTO Index', -> extend $2, proto: yes
]
IndexValue: [
o 'Expression', -> new Index $1
o 'Slice', -> new Slice $1
]
# In CoffeeScript, an object literal is simply a list of assignments.
Object: [
@@ -334,9 +338,9 @@ grammar =
# Array slice literals.
Slice: [
o 'INDEX_START Expression RangeDots Expression INDEX_END', -> new Range $2, $4, $3
o 'INDEX_START Expression RangeDots INDEX_END', -> new Range $2, null, $3
o 'INDEX_START RangeDots Expression INDEX_END', -> new Range null, $3, $2
o 'Expression RangeDots Expression', -> new Range $1, $3, $2
o 'Expression RangeDots', -> new Range $1, null, $2
o 'RangeDots Expression', -> new Range null, $2, $1
]
# The **ArgList** is both the list of objects passed into a function call,

View File

@@ -80,7 +80,8 @@ exports.Lexer = class Lexer
@token 'OWN', id
return id.length
forcedIdentifier = colon or
(prev = last @tokens) and not prev.spaced and prev[0] in ['.', '?.', '@', '::']
(prev = last @tokens) and (prev[0] in ['.', '?.', '::'] or
not prev.spaced and prev[0] is '@')
tag = 'IDENTIFIER'
if id in JS_KEYWORDS or
@@ -113,7 +114,7 @@ exports.Lexer = class Lexer
@identifierError id
unless forcedIdentifier
id = COFFEE_ALIASES[id] if COFFEE_ALIASES.hasOwnProperty id
id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES
tag = switch id
when '!' then 'UNARY'
when '==', '!=' then 'COMPARE'
@@ -170,11 +171,11 @@ exports.Lexer = class Lexer
commentToken: ->
return 0 unless match = @chunk.match COMMENT
[comment, here] = match
@line += count comment, '\n'
if here
@token 'HERECOMMENT', @sanitizeHeredoc here,
herecomment: true, indent: Array(@indent + 1).join(' ')
@token 'TERMINATOR', '\n'
@line += count comment, '\n'
comment.length
# Matches JavaScript interpolated directly into the source via backticks.
@@ -343,8 +344,11 @@ exports.Lexer = class Lexer
# erasing all external indentation on the left-hand side.
sanitizeHeredoc: (doc, options) ->
{indent, herecomment} = options
return doc if herecomment and 0 > doc.indexOf '\n'
unless herecomment
if herecomment
if HEREDOC_ILLEGAL.test doc
throw new Error "block comment cannot contain \"*/\", starting on line #{@line + 1}"
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
@@ -367,7 +371,7 @@ exports.Lexer = class Lexer
stack.push tok
when '(', 'CALL_START'
if stack.length then stack.pop()
else
else if tok[0] is '('
tok[0] = 'PARAM_START'
return this
this
@@ -508,7 +512,8 @@ JS_KEYWORDS = [
# CoffeeScript-only keywords.
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']
COFFEE_KEYWORDS.push op for op of COFFEE_ALIASES =
COFFEE_ALIAS_MAP =
and : '&&'
or : '||'
is : '=='
@@ -518,6 +523,9 @@ COFFEE_KEYWORDS.push op for op of COFFEE_ALIASES =
no : 'false'
on : 'true'
off : 'false'
COFFEE_ALIASES = (key for key of COFFEE_ALIAS_MAP)
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES
# The list of keywords that are reserved by JavaScript, but not used, or are
# used by CoffeeScript internally. We throw an error when these are encountered,
@@ -571,7 +579,7 @@ JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/
# Regex-matching-regexes.
REGEX = /// ^
/ (?! \s ) # disallow leading whitespace
/ (?! [\s=] ) # disallow leading whitespace or equals signs
[^ [ / \n \\ ]* # every other thing
(?:
(?: \\[\s\S] # anything escaped
@@ -593,9 +601,11 @@ MULTILINER = /\n/g
HEREDOC_INDENT = /\n+([^\n\S]*)/g
HEREDOC_ILLEGAL = /\*\//
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?!\.) | :: ) ///
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///
TRAILING_SPACES = /\s+$/

View File

@@ -48,7 +48,7 @@ exports.Base = class Base
# Statements converted into expressions via closure-wrapping share a scope
# object with their parent closure, to preserve the expected lexical scope.
compileClosure: (o) ->
if @jumps()
if @jumps() or this instanceof Throw
throw SyntaxError 'cannot use a pure statement in an expression.'
o.sharedScope = yes
Closure.wrap(this).compileNode o
@@ -233,7 +233,6 @@ exports.Block = class Block extends Base
o.scope = new Scope null, this, null
o.level = LEVEL_TOP
code = @compileWithDeclarations o
code = code.replace TRAILING_WHITESPACE, ''
if o.bare then code else "(function() {\n#{code}\n}).call(this);\n"
# Compile the expressions body for the contents of a function, with
@@ -251,7 +250,7 @@ exports.Block = class Block extends Base
post = @compileNode o
{scope} = o
if scope.expressions is this
if not o.globals and o.scope.hasDeclarations()
if o.scope.hasDeclarations()
code += "#{@tab}var #{ scope.declaredVariables().join(', ') };\n"
if scope.hasAssignments
code += "#{@tab}var #{ multident scope.assignedVariables().join(', '), @tab };\n"
@@ -405,19 +404,22 @@ exports.Value = class Value extends Base
# Unfold a soak into an `If`: `a?.b` -> `a.b if a?`
unfoldSoak: (o) ->
if ifn = @base.unfoldSoak o
Array::push.apply ifn.body.properties, @properties
return ifn
for prop, i in @properties when prop.soak
prop.soak = off
fst = new Value @base, @properties.slice 0, i
snd = new Value @base, @properties.slice i
if fst.isComplex()
ref = new Literal o.scope.freeVariable 'ref'
fst = new Parens new Assign ref, fst
snd.base = ref
return new If new Existence(fst), snd, soak: on
null
return @unfoldedSoak if @unfoldedSoak?
result = do =>
if ifn = @base.unfoldSoak o
Array::push.apply ifn.body.properties, @properties
return ifn
for prop, i in @properties when prop.soak
prop.soak = off
fst = new Value @base, @properties.slice 0, i
snd = new Value @base, @properties.slice i
if fst.isComplex()
ref = new Literal o.scope.freeVariable 'ref'
fst = new Parens new Assign ref, fst
snd.base = ref
return new If new Existence(fst), snd, soak: on
null
@unfoldedSoak = result or no
#### Comment
@@ -478,7 +480,7 @@ exports.Call = class Call extends Base
rite = new Value left
rite = new Call rite, @args
rite.isNew = @isNew
left = new Literal "typeof #{ left.compile o } == \"function\""
left = new Literal "typeof #{ left.compile o } === \"function\""
return new If left, new Value(rite), soak: yes
call = this
list = []
@@ -499,12 +501,31 @@ exports.Call = class Call extends Base
ifn = unfoldSoak o, call, 'variable'
ifn
# Walk through the objects in the arguments, moving over simple values.
# This allows syntax like `call a: b, c` into `call({a: b}, c);`
filterImplicitObjects: (list) ->
nodes = []
for node in list
unless node.isObject?() and node.base.generated
nodes.push node
continue
obj = null
for prop in node.base.properties
if prop instanceof Assign
nodes.push obj = new Obj properties = [], true if not obj
properties.push prop
else
nodes.push prop
obj = null
nodes
# Compile a vanilla function call.
compileNode: (o) ->
@variable?.front = @front
if code = Splat.compileSplattedArray o, @args, true
return @compileSplat o, code
args = (arg.compile o, LEVEL_LIST for arg in @args).join ', '
args = @filterImplicitObjects @args
args = (arg.compile o, LEVEL_LIST for arg in args).join ', '
if @isSuper
@superReference(o) + ".call(this#{ args and ', ' + args })"
else
@@ -524,11 +545,11 @@ exports.Call = class Call extends Base
if @isNew
idt = @tab + TAB
return """
(function(func, args, ctor) {
#{idt}ctor.prototype = func.prototype;
#{idt}var child = new ctor, result = func.apply(child, args);
#{idt}return typeof result == "object" ? result : child;
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})
(function(func, args, ctor) {
#{idt}ctor.prototype = func.prototype;
#{idt}var child = new ctor, result = func.apply(child, args);
#{idt}return typeof result === "object" ? result : child;
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})
"""
base = new Value @variable
if (name = base.properties.pop()) and base.isComplex()
@@ -619,27 +640,29 @@ exports.Range = class Range extends Base
# needed to iterate over the values in the range. Used by comprehensions.
compileNode: (o) ->
@compileVariables o
return @compileArray(o) unless o.index
return @compileSimple(o) if @fromNum and @toNum
return @compileArray(o) unless o.index
return @compileSimple(o) if @fromNum and @toNum
idx = del o, 'index'
step = del o, 'step'
vars = "#{idx} = #{@from}" + if @to isnt @toVar then ", #{@to}" else ''
intro = "(#{@fromVar} <= #{@toVar} ? #{idx}"
compare = "#{intro} <#{@equals} #{@toVar} : #{idx} >#{@equals} #{@toVar})"
stepPart = if step then step.compile(o) else '1'
incr = if step then "#{idx} += #{stepPart}" else "#{intro} += #{stepPart} : #{idx} -= #{stepPart})"
"#{vars}; #{compare}; #{incr}"
stepvar = o.scope.freeVariable "step" if step
varPart = "#{idx} = #{@from}" + ( if @to isnt @toVar then ", #{@to}" else '' ) + if step then ", #{stepvar} = #{step.compile(o)}" else ''
cond = "#{@fromVar} <= #{@toVar}"
condPart = "#{cond} ? #{idx} <#{@equals} #{@toVar} : #{idx} >#{@equals} #{@toVar}"
stepPart = if step then "#{idx} += #{stepvar}" else "#{cond} ? #{idx}++ : #{idx}--"
"#{varPart}; #{condPart}; #{stepPart}"
# Compile a simple range comprehension, with integers.
compileSimple: (o) ->
[from, to] = [+@fromNum, +@toNum]
idx = del o, 'index'
step = del o, 'step'
step and= "#{idx} += #{step.compile(o)}"
if from <= to
"#{idx} = #{from}; #{idx} <#{@equals} #{to}; #{step or "#{idx}++"}"
else
"#{idx} = #{from}; #{idx} >#{@equals} #{to}; #{step or "#{idx}--"}"
stepvar = o.scope.freeVariable "step" if step
varPart = "#{idx} = #{from}"
varPart += ", #{stepvar} = #{step.compile(o)}" if step
condPart = if from <= to then "#{idx} <#{@equals} #{to}" else "#{idx} >#{@equals} #{to}"
stepPart = "#{idx} += #{stepvar}" if step
stepPart = ( if from <= to then "#{idx}++" else "#{idx}--" ) if not step
"#{varPart}; #{condPart}; #{stepPart}"
# When used as a value, expand the range into the equivalent array.
compileArray: (o) ->
@@ -653,11 +676,11 @@ exports.Range = class Range extends Base
pre = "\n#{idt}#{result} = [];"
if @fromNum and @toNum
o.index = i
body = @compileSimple o
body = @compileSimple o
else
vars = "#{i} = #{@from}" + if @to isnt @toVar then ", #{@to}" else ''
clause = "#{@fromVar} <= #{@toVar} ?"
body = "var #{vars}; #{clause} #{i} <#{@equals} #{@toVar} : #{i} >#{@equals} #{@toVar}; #{clause} #{i} += 1 : #{i} -= 1"
vars = "#{i} = #{@from}" + if @to isnt @toVar then ", #{@to}" else ''
cond = "#{@fromVar} <= #{@toVar}"
body = "var #{vars}; #{cond} ? #{i} <#{@equals} #{@toVar} : #{i} >#{@equals} #{@toVar}; #{cond} ? #{i}++ : #{i}--"
post = "{ #{result}.push(#{i}); }\n#{idt}return #{result};\n#{o.indent}"
"(function() {#{pre}\n#{idt}for (#{body})#{post}}).apply(this, arguments)"
@@ -701,6 +724,9 @@ exports.Obj = class Obj extends Base
compileNode: (o) ->
props = @properties
return (if @front then '({})' else '{}') unless props.length
if @generated
for node in props when node instanceof Value
throw new Error 'cannot have an implicit value in an implicit object'
idt = o.indent += TAB
lastNoncom = @lastNonComment @properties
props = for prop, i in props
@@ -735,11 +761,14 @@ exports.Arr = class Arr extends Base
children: ['objects']
filterImplicitObjects: Call::filterImplicitObjects
compileNode: (o) ->
return '[]' unless @objects.length
o.indent += TAB
return code if code = Splat.compileSplattedArray o, @objects
code = (obj.compile o, LEVEL_LIST for obj in @objects).join ', '
objs = @filterImplicitObjects @objects
return code if code = Splat.compileSplattedArray o, objs
code = (obj.compile o, LEVEL_LIST for obj in objs).join ', '
if code.indexOf('\n') >= 0
"[\n#{o.indent}#{code}\n#{@tab}]"
else
@@ -787,13 +816,13 @@ exports.Class = class Class extends Base
if @boundFuncs.length
for bvar in @boundFuncs
bname = bvar.compile o
@ctor.body.unshift new Literal "this.#{bname} = #{utility 'bind'}(this.#{bname}, this);"
@ctor.body.unshift new Literal "this.#{bname} = #{utility 'bind'}(this.#{bname}, this)"
# Merge the properties from a top-level object as prototypal properties
# on the class.
addProperties: (node, name) ->
addProperties: (node, name, o) ->
props = node.base.properties.slice 0
while assign = props.shift()
exprs = while assign = props.shift()
if assign instanceof Assign
base = assign.variable.base
delete assign.context
@@ -806,7 +835,8 @@ exports.Class = class Class extends Base
if func instanceof Code
assign = @ctor = func
else
assign = @ctor = new Assign(new Value(new Literal name), func)
@externalCtor = o.scope.freeVariable 'class'
assign = new Assign new Literal(@externalCtor), func
else
unless assign.variable.this
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')])
@@ -814,15 +844,16 @@ exports.Class = class Class extends Base
@boundFuncs.push base
func.bound = no
assign
compact exprs
# Walk the body of the class, looking for prototype properties to be converted.
walkBody: (name) ->
walkBody: (name, o) ->
@traverseChildren false, (child) =>
return false if child instanceof Class
if child instanceof Block
for node, i in exps = child.expressions
if node instanceof Value and node.isObject(true)
exps[i] = @addProperties node, name
exps[i] = @addProperties node, name, o
child.expressions = exps = flatten exps
# Make sure that a constructor is defined for the class, and properly
@@ -830,7 +861,8 @@ exports.Class = class Class extends Base
ensureConstructor: (name) ->
if not @ctor
@ctor = new Code
@ctor.body.push new Call 'super', [new Splat new Literal 'arguments'] if @parent
@ctor.body.push new Literal "#{name}.__super__.constructor.apply(this, arguments)" if @parent
@ctor.body.push new Literal "#{@externalCtor}.apply(this, arguments)" if @externalCtor
@body.expressions.unshift @ctor
@ctor.ctor = @ctor.name = name
@ctor.klass = null
@@ -845,9 +877,10 @@ exports.Class = class Class extends Base
lname = new Literal name
@setContext name
@walkBody name
@body.expressions.unshift new Extends lname, @parent if @parent
@walkBody name, o
@ensureConstructor name
@body.expressions.unshift new Extends lname, @parent if @parent
@body.expressions.unshift @ctor unless @ctor instanceof Code
@body.expressions.push lname
@addBoundFunctions o
@@ -884,18 +917,18 @@ exports.Assign = class Assign extends Base
return @compileSplice o if @variable.isSplice()
return @compileConditional o if @context in ['||=', '&&=', '?=']
name = @variable.compile o, LEVEL_LIST
if @value instanceof Code and match = @METHOD_DEF.exec name
@value.name = match[2]
@value.klass = match[1] if match[1]
val = @value.compile o, LEVEL_LIST
return "#{name}: #{val}" if @context is 'object'
unless @variable.isAssignable()
unless @context or @variable.isAssignable()
throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned."
unless @context or isValue and (@variable.namespaced or @variable.hasProperties())
if @param
o.scope.add name, 'var'
else
o.scope.find name
if @value instanceof Code and match = @METHOD_DEF.exec name
@value.name = match[2]
@value.klass = match[1] if match[1]
val = @value.compile o, LEVEL_LIST
return "#{name}: #{val}" if @context is 'object'
val = name + " #{ @context or '=' } " + val
if o.level <= LEVEL_LIST then val else "(#{val})"
@@ -908,7 +941,6 @@ exports.Assign = class Assign extends Base
{value} = this
{objects} = @variable.base
unless olen = objects.length
return false if top
code = value.compile o
return if o.level >= LEVEL_OP then "(#{code})" else code
isObject = @variable.isObject()
@@ -969,7 +1001,7 @@ exports.Assign = class Assign extends Base
val = new Value new Literal(vvar), [new (if acc then Access else Index) idx]
assigns.push new Assign(obj, val, null, param: @param).compile o, LEVEL_TOP
assigns.push vvar unless top
code = (compact assigns).join ', '
code = assigns.join ', '
if o.level < LEVEL_LIST then code else "(#{code})"
# When compiling a conditional assignment, take care to ensure that the
@@ -1026,10 +1058,10 @@ exports.Code = class Code extends Base
o.scope.shared = del o, 'sharedScope'
o.indent += TAB
delete o.bare
delete o.globals
vars = []
exprs = []
for param in @params when param.splat
o.scope.add param.name.value, 'var' if param.name.value
splats = new Assign new Value(new Arr(p.asReference o for p in @params)),
new Value new Literal 'arguments'
break
@@ -1188,10 +1220,13 @@ exports.While = class While extends Base
exports.Op = class Op extends Base
constructor: (op, first, second, flip) ->
return new In first, second if op is 'in'
return new Call first, first.params or [] if op is 'do'
if op is 'do'
call = new Call first, first.params or []
call.do = yes
return call
if op is 'new'
return first.newInstance() if first instanceof Call
first = new Parens first if first instanceof Code and first.bound
return first.newInstance() if first instanceof Call and not first.do
first = new Parens first if first instanceof Code and first.bound or first.do
@operator = CONVERSIONS[op] or op
@first = first
@second = second
@@ -1273,18 +1308,19 @@ exports.Op = class Op extends Base
compileExistence: (o) ->
if @first.isComplex()
ref = o.scope.freeVariable 'ref'
fst = new Parens new Assign new Literal(ref), @first
ref = new Literal o.scope.freeVariable 'ref'
fst = new Parens new Assign ref, @first
else
fst = @first
ref = fst.compile o
new Existence(fst).compile(o) + " ? #{ref} : #{ @second.compile o, LEVEL_LIST }"
ref = fst
new If(new Existence(fst), ref, type: 'if').addElse(@second).compile o
# Compile a unary **Op**.
compileUnary: (o) ->
parts = [op = @operator]
parts.push ' ' if op in ['new', 'typeof', 'delete'] or
op in ['+', '-'] and @first instanceof Op and @first.operator is op
@first = new Parens @first if op is 'new' and @first.isStatement o
parts.push @first.compile o, LEVEL_OP
parts.reverse() if @flip
parts.join ''
@@ -1311,6 +1347,7 @@ exports.In = class In extends Base
[cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || ']
tests = for item, i in @array.base.objects
(if i then ref else sub) + cmp + item.compile o, LEVEL_OP
return 'false' if tests.length is 0
tests = tests.join cnj
if o.level < LEVEL_OP then tests else "(#{tests})"
@@ -1390,9 +1427,9 @@ exports.Existence = class Existence extends Base
code = @expression.compile o, LEVEL_OP
code = if IDENTIFIER.test(code) and not o.scope.check code
if @negated
"typeof #{code} == \"undefined\" || #{code} === null"
"typeof #{code} === \"undefined\" || #{code} === null"
else
"typeof #{code} != \"undefined\" && #{code} !== null"
"typeof #{code} !== \"undefined\" && #{code} !== null"
else
sym = if @negated then '==' else '!='
"#{code} #{sym} null"
@@ -1462,50 +1499,53 @@ exports.For = class For extends Base
# 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
index = @index and @index.compile o, LEVEL_LIST
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
index = @index and @index.compile o, LEVEL_LIST
scope.find(name, immediate: yes) if name and not @pattern
scope.find(index, immediate: yes) if index
rvar = scope.freeVariable 'results' if @returns
ivar = (if @range then name else index) or scope.freeVariable 'i'
name = ivar if @pattern
varPart = ''
guardPart = ''
defPart = ''
idt1 = @tab + TAB
rvar = scope.freeVariable 'results' if @returns
ivar = (if @range then name else index) or scope.freeVariable 'i'
# the `_by` variable is created twice in `Range`s if we don't prevent it from being declared here
stepvar = scope.freeVariable "step" if @step and not @range
name = ivar if @pattern
varPart = ''
guardPart = ''
defPart = ''
idt1 = @tab + TAB
if @range
forPart = source.compile merge(o, {index: ivar, @step})
else
svar = @source.compile o, LEVEL_LIST
svar = @source.compile o, LEVEL_LIST
if (name or @own) and not IDENTIFIER.test svar
defPart = "#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n"
svar = ref
defPart = "#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n"
svar = ref
if name and not @pattern
namePart = "#{name} = #{svar}[#{ivar}]"
namePart = "#{name} = #{svar}[#{ivar}]"
unless @object
lvar = scope.freeVariable 'len'
stepPart = if @step then "#{ivar} += #{ @step.compile(o, LEVEL_OP) }" else "#{ivar}++"
forPart = "#{ivar} = 0, #{lvar} = #{svar}.length; #{ivar} < #{lvar}; #{stepPart}"
lvar = scope.freeVariable 'len'
forVarPart = "#{ivar} = 0, #{lvar} = #{svar}.length" + if @step then ", #{stepvar} = #{@step.compile(o, LEVEL_OP)}" else ''
stepPart = if @step then "#{ivar} += #{stepvar}" else "#{ivar}++"
forPart = "#{forVarPart}; #{ivar} < #{lvar}; #{stepPart}"
if @returns
resultPart = "#{@tab}#{rvar} = [];\n"
returnResult = "\n#{@tab}return #{rvar};"
body = Push.wrap rvar, body
resultPart = "#{@tab}#{rvar} = [];\n"
returnResult = "\n#{@tab}return #{rvar};"
body = Push.wrap rvar, body
if @guard
body = Block.wrap [new If @guard, body]
body = Block.wrap [new If @guard, body]
if @pattern
body.expressions.unshift new Assign @name, new Literal "#{svar}[#{ivar}]"
defPart += @pluckDirectCall o, body
varPart = "\n#{idt1}#{namePart};" if namePart
defPart += @pluckDirectCall o, body
varPart = "\n#{idt1}#{namePart};" if namePart
if @object
forPart = "#{ivar} in #{svar}"
guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" if @own
body = body.compile merge(o, indent: idt1), LEVEL_TOP
body = '\n' + body + '\n' if body
forPart = "#{ivar} in #{svar}"
guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" if @own
body = body.compile merge(o, indent: idt1), LEVEL_TOP
body = '\n' + body + '\n' if body
"""
#{defPart}#{resultPart or ''}#{@tab}for (#{forPart}) {#{guardPart}#{varPart}#{body}#{@tab}}#{returnResult or ''}
"""
@@ -1669,8 +1709,7 @@ Closure =
return expressions if expressions.jumps()
func = new Code [], Block.wrap [expressions]
args = []
if (mentionsArgs = expressions.contains @literalArgs) or
( expressions.contains @literalThis)
if (mentionsArgs = expressions.contains @literalArgs) or expressions.contains @literalThis
meth = new Literal if mentionsArgs then 'apply' else 'call'
args = [new Literal 'this']
args.push new Literal 'arguments' if mentionsArgs
@@ -1741,10 +1780,6 @@ LEVEL_ACCESS = 6 # ...[0]
# Tabs are two spaces for pretty printing.
TAB = ' '
# Trim out all trailing whitespace, so that the generated code plays nice
# with Git.
TRAILING_WHITESPACE = /[ \t]+$/gm
IDENTIFIER = /^[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*$/
SIMPLENUM = /^[+-]?\d+$/

View File

@@ -6,40 +6,100 @@
# Require the **coffee-script** module to get access to the compiler.
CoffeeScript = require './coffee-script'
helpers = require './helpers'
readline = require 'readline'
{inspect} = require 'util'
{Script} = require 'vm'
# REPL Setup
# Config
enableColours = no
unless process.platform is 'win32'
enableColours = not process.env.NODE_DISABLE_COLORS
# Start by opening up `stdin` and `stdout`.
stdin = process.openStdin()
stdin = process.openStdin()
stdout = process.stdout
# Log an error.
error = (err) ->
stdout.write (err.stack or err.toString()) + '\n\n'
# Quick alias for quitting the REPL.
helpers.extend global, quit: -> process.exit(0)
# The current backlog of multi-line code.
backlog = ''
# The main REPL function. **run** is called every time a line of code is entered.
# Attempt to evaluate the command. If there's an exception, print it out instead
# of exiting.
run = (buffer) ->
try
val = CoffeeScript.eval buffer.toString(), bare: on, globals: on, filename: 'repl'
process.stdout.write val + '\n' if val isnt undefined
catch err
error err
repl.prompt()
run = do ->
sandbox =
require: require
module : { exports: {} }
sandbox[g] = global[g] for g of global
sandbox.global = sandbox
sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox
(buffer) ->
code = backlog += '\n' + buffer.toString()
if code[code.length - 1] is '\\'
return backlog = backlog[0...backlog.length - 1]
backlog = ''
try
val = CoffeeScript.eval code, {
sandbox,
bare: on,
filename: 'repl'
}
unless val is undefined
process.stdout.write inspect(val, no, 2, enableColours) + '\n'
catch err
error err
repl.prompt()
## Autocompletion
# Regexes to match complete-able bits of text.
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/
SIMPLEVAR = /\s*(\w*)$/i
# Returns a list of completions, and the completed text.
autocomplete = (text) ->
completeAttribute(text) or completeVariable(text) or [[], text]
# Attempt to autocomplete a chained dotted attribute: `one.two.three`.
completeAttribute = (text) ->
if match = text.match ACCESSOR
[all, obj, prefix] = match
try
val = Script.runInThisContext obj
catch error
return [[], text]
completions = getCompletions prefix, getPropertyNames val
[completions, prefix]
# Attempt to autocomplete an in-scope free variable: `one`.
completeVariable = (text) ->
if free = text.match(SIMPLEVAR)?[1]
scope = Script.runInThisContext 'this'
completions = getCompletions free, CoffeeScript.RESERVED.concat(getPropertyNames scope)
[completions, free]
# Return elements of candidates for which `prefix` is a prefix.
getCompletions = (prefix, candidates) ->
(el for el in candidates when el.indexOf(prefix) is 0)
# Return all "own" properties of an object.
getPropertyNames = (obj) ->
(name for own name of obj)
# Make sure that uncaught exceptions don't kill the REPL.
process.on 'uncaughtException', error
# Create the REPL by listening to **stdin**.
if readline.createInterface.length < 3
repl = readline.createInterface stdin
repl = readline.createInterface stdin, autocomplete
stdin.on 'data', (buffer) -> repl.write buffer
else
repl = readline.createInterface stdin, stdout
repl = readline.createInterface stdin, stdout, autocomplete
repl.setPrompt 'coffee> '
repl.on 'close', -> stdin.destroy()

View File

@@ -104,7 +104,10 @@ class exports.Rewriter
not (two?[0] is ':' or one?[0] is '@' and three?[0] is ':')) or
(tag is ',' and one and
one[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT'])
action = (token, i) -> @tokens.splice i, 0, ['}', '}', token[2]]
action = (token, i) ->
tok = ['}', '}', token[2]]
tok.generated = yes
@tokens.splice i, 0, tok
@scanTokens (token, i, tokens) ->
if (tag = token[0]) in EXPRESSION_START
stack.push [(if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag), i]
@@ -143,6 +146,7 @@ class exports.Rewriter
seenSingle = no
noCall = no if tag in LINEBREAKS
token.call = yes if prev and not prev.spaced and tag is '?'
return 1 if token.fromThen
return 1 unless callObject or
prev?.spaced and (prev.call or prev[0] in IMPLICIT_FUNC) and
(tag in IMPLICIT_CALL or not (token.spaced or token.newLine) and tag in IMPLICIT_UNSPACED_CALL)

View File

@@ -17,7 +17,7 @@ exports.Scope = class Scope
# as well as a reference to the **Block** node is belongs to, which is
# where it should declare its variables, and a reference to the function that
# it wraps.
constructor:(@parent, @expressions, @method) ->
constructor: (@parent, @expressions, @method) ->
@variables = [{name: 'arguments', type: 'arguments'}]
@positions = {}
Scope.root = this unless @parent
@@ -66,7 +66,7 @@ exports.Scope = class Scope
# compiler-generated variable. `_var`, `_var2`, and so on...
freeVariable: (type) ->
index = 0
index++ while @check((temp = @temporary type, index), true)
index++ while @check((temp = @temporary type, index))
@add temp, 'var', yes
temp

View File

@@ -1,37 +0,0 @@
# Array Literals
# --------------
# * Array Literals
# * Splats in Array Literals
# TODO: refactor array literal tests
# TODO: add indexing and method invocation tests: [1][0] is 1, [].toString()
trailingComma = [1, 2, 3,]
ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)
trailingComma = [
1, 2, 3,
4, 5, 6
7, 8, 9,
]
(sum = (sum or 0) + n) for n in trailingComma
a = [((x) -> x), ((x) -> x * x)]
ok a.length is 2
# Funky indentation within non-comma-seperated arrays.
result = [['a']
{b: 'c'}]
ok result[0][0] is 'a'
ok result[1]['b'] is 'c'
#### Splats in Array Literals
test "array splat expansions with assignments", ->
nums = [1, 2, 3]
list = [a = 0, nums..., b = 4]
eq 0, a
eq 4, b
arrayEq [0,1,2,3,4], list

77
test/arrays.coffee Normal file
View File

@@ -0,0 +1,77 @@
# Array Literals
# --------------
# * Array Literals
# * Splats in Array Literals
# TODO: add indexing and method invocation tests: [1][0] is 1, [].toString()
test "trailing commas", ->
trailingComma = [1, 2, 3,]
ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)
trailingComma = [
1, 2, 3,
4, 5, 6
7, 8, 9,
]
(sum = (sum or 0) + n) for n in trailingComma
a = [((x) -> x), ((x) -> x * x)]
ok a.length is 2
test "incorrect indentation without commas", ->
result = [['a']
{b: 'c'}]
ok result[0][0] is 'a'
ok result[1]['b'] is 'c'
# Splats in Array Literals
test "array splat expansions with assignments", ->
nums = [1, 2, 3]
list = [a = 0, nums..., b = 4]
eq 0, a
eq 4, b
arrayEq [0,1,2,3,4], list
test "mixed shorthand objects in array lists", ->
arr = [
a:1
'b'
c:1
]
ok arr.length is 3
ok arr[2].c is 1
arr = [b: 1, a: 2, 100]
eq arr[1], 100
arr = [a:0, b:1, (1 + 1)]
eq arr[1], 2
arr = [a:1, 'a', b:1, 'b']
eq arr.length, 4
eq arr[2].b, 1
eq arr[3], 'b'
test "array splats with nested arrays", ->
nonce = {}
a = [nonce]
list = [1, 2, a...]
eq list[0], 1
eq list[2], nonce
a = [[nonce]]
list = [1, 2, a...]
arrayEq list, [1, 2, [nonce]]
test "#1274: `[] = a()` compiles to `false` instead of `a()`", ->
a = false
fn = -> a = true
[] = fn()
ok a

View File

@@ -1,8 +1,6 @@
# Assignment
# ----------
# TODO: organize assignment file
# * Assignment
# * Compound Assignment
# * Destructuring Assignment
@@ -27,7 +25,7 @@ test "compound assignments should not declare", ->
eq Math, (-> Math or= 0)()
#### Compound Assignment
# Compound Assignment
test "boolean operators", ->
nonce = {}
@@ -136,7 +134,7 @@ test "more compound assignment", ->
eq c, val
#### Destructuring Assignment
# Destructuring Assignment
test "empty destructuring assignment", ->
{} = [] = undefined
@@ -231,6 +229,10 @@ test "destructuring assignment against an expression", ->
eq a, y
eq b, z
test "bracket insertion when necessary", ->
[a] = [0] ? [1]
eq a, 0
# for implicit destructuring assignment in comprehensions, see the comprehension tests
test "destructuring assignment with context (@) properties", ->
@@ -251,7 +253,7 @@ test "#1024", ->
eq 2 * [] = 3 + 5, 16
#### Existential Assignment
# Existential Assignment
test "existential assignment", ->
nonce = {}

View File

@@ -1,21 +0,0 @@
# Boolean Literals
# ----------------
# TODO: add method invocation tests: true.toString() is "true"
#764: Boolean should be indexable
toString = Boolean::toString
eq toString, true['toString']
eq toString, false['toString']
eq toString, yes['toString']
eq toString, no['toString']
eq toString, on['toString']
eq toString, off['toString']
eq toString, true.toString
eq toString, false.toString
eq toString, yes.toString
eq toString, no.toString
eq toString, on.toString
eq toString, off.toString

21
test/booleans.coffee Normal file
View File

@@ -0,0 +1,21 @@
# Boolean Literals
# ----------------
# TODO: add method invocation tests: true.toString() is "true"
test "#764 Booleans should be indexable", ->
toString = Boolean::toString
eq toString, true['toString']
eq toString, false['toString']
eq toString, yes['toString']
eq toString, no['toString']
eq toString, on['toString']
eq toString, off['toString']
eq toString, true.toString
eq toString, false.toString
eq toString, yes.toString
eq toString, no.toString
eq toString, on.toString
eq toString, off.toString

View File

@@ -1,4 +0,0 @@
# Cake
# ----
# TODO: add tests

View File

@@ -5,113 +5,119 @@
# * Class Instantiation
# * Inheritance and Super
# TODO: refactor class tests
test "classes with a four-level inheritance chain", ->
# Test classes with a four-level inheritance chain.
class Base
func: (string) ->
"zero/#{string}"
class Base
func: (string) ->
"zero/#{string}"
@static: (string) ->
"static/#{string}"
@static: (string) ->
"static/#{string}"
class FirstChild extends Base
func: (string) ->
class FirstChild extends Base
func: (string) ->
super('one/') + string
SecondChild = class extends FirstChild
func: (string) ->
super('two/') + string
thirdCtor = ->
@array = [1, 2, 3]
class ThirdChild extends SecondChild
constructor: -> thirdCtor.call this
# Gratuitous comment for testing.
func: (string) ->
super('three/') + string
result = (new ThirdChild).func 'four'
ok result is 'zero/one/two/three/four'
ok Base.static('word') is 'static/word'
FirstChild::func = (string) ->
super('one/').length + string
result = (new ThirdChild).func 'four'
ok result is '9two/three/four'
ok (new ThirdChild).array.join(' ') is '1 2 3'
test "constructors with inheritance and super", ->
identity = (f) -> f
class TopClass
constructor: (arg) ->
@prop = 'top-' + arg
class SuperClass extends TopClass
constructor: (arg) ->
identity super 'super-' + arg
class SubClass extends SuperClass
constructor: ->
identity super 'sub'
ok (new SubClass).prop is 'top-super-sub'
test "Overriding the static property new doesn't clobber Function::new", ->
class OneClass
@new: 'new'
function: 'function'
constructor: (name) -> @name = name
class TwoClass extends OneClass
delete TwoClass.new
Function.prototype.new = -> new this arguments...
ok (TwoClass.new('three')).name is 'three'
ok (new OneClass).function is 'function'
ok OneClass.new is 'new'
delete Function.prototype.new
test "basic classes, again, but in the manual prototype style", ->
Base = ->
Base::func = (string) ->
'zero/' + string
Base::['func-func'] = (string) ->
"dynamic-#{string}"
FirstChild = ->
SecondChild = ->
ThirdChild = ->
@array = [1, 2, 3]
this
ThirdChild extends SecondChild extends FirstChild extends Base
FirstChild::func = (string) ->
super('one/') + string
SecondChild = class extends FirstChild
func: (string) ->
SecondChild::func = (string) ->
super('two/') + string
thirdCtor = ->
@array = [1, 2, 3]
class ThirdChild extends SecondChild
constructor: -> thirdCtor.call this
# Gratuitous comment for testing.
func: (string) ->
ThirdChild::func = (string) ->
super('three/') + string
result = (new ThirdChild).func 'four'
result = (new ThirdChild).func 'four'
ok result is 'zero/one/two/three/four'
ok Base.static('word') is 'static/word'
ok result is 'zero/one/two/three/four'
FirstChild::func = (string) ->
super('one/').length + string
result = (new ThirdChild).func 'four'
ok result is '9two/three/four'
ok (new ThirdChild).array.join(' ') is '1 2 3'
ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'
identity = (f) -> f
class TopClass
constructor: (arg) ->
@prop = 'top-' + arg
class SuperClass extends TopClass
constructor: (arg) ->
identity super 'super-' + arg
class SubClass extends SuperClass
constructor: ->
identity super 'sub'
ok (new SubClass).prop is 'top-super-sub'
class OneClass
@new: 'new'
function: 'function'
constructor: (name) -> @name = name
class TwoClass extends OneClass
delete TwoClass.new
Function.prototype.new = -> new this arguments...
ok (TwoClass.new('three')).name is 'three'
ok (new OneClass).function is 'function'
ok OneClass.new is 'new'
delete Function.prototype.new
# And now the same tests, but written in the manual style:
Base = ->
Base::func = (string) ->
'zero/' + string
Base::['func-func'] = (string) ->
"dynamic-#{string}"
FirstChild = ->
SecondChild = ->
ThirdChild = ->
@array = [1, 2, 3]
this
ThirdChild extends SecondChild extends FirstChild extends Base
FirstChild::func = (string) ->
super('one/') + string
SecondChild::func = (string) ->
super('two/') + string
ThirdChild::func = (string) ->
super('three/') + string
result = (new ThirdChild).func 'four'
ok result is 'zero/one/two/three/four'
ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'
test "super with plain ol' functions as the original constructors", ->
TopClass = (arg) ->
@prop = 'top-' + arg
@@ -131,283 +137,342 @@ SubClass extends SuperClass
ok (new SubClass).prop is 'top-super-sub'
# '@' referring to the current instance, and not being coerced into a call.
class ClassName
amI: ->
@ instanceof ClassName
test "'@' referring to the current instance, and not being coerced into a call", ->
obj = new ClassName
ok obj.amI()
class ClassName
amI: ->
@ instanceof ClassName
obj = new ClassName
ok obj.amI()
# super() calls in constructors of classes that are defined as object properties.
class Hive
constructor: (name) -> @name = name
test "super() calls in constructors of classes that are defined as object properties", ->
class Hive.Bee extends Hive
constructor: (name) -> super
class Hive
constructor: (name) -> @name = name
maya = new Hive.Bee 'Maya'
ok maya.name is 'Maya'
class Hive.Bee extends Hive
constructor: (name) -> super
maya = new Hive.Bee 'Maya'
ok maya.name is 'Maya'
# Class with JS-keyword properties.
class Class
class: 'class'
name: -> @class
test "classes with JS-keyword properties", ->
instance = new Class
ok instance.class is 'class'
ok instance.name() is 'class'
class Class
class: 'class'
name: -> @class
instance = new Class
ok instance.class is 'class'
ok instance.name() is 'class'
# Classes with methods that are pre-bound to the instance.
# ... or statically, to the class.
class Dog
test "Classes with methods that are pre-bound to the instance, or statically, to the class", ->
constructor: (name) ->
@name = name
class Dog
constructor: (name) ->
@name = name
bark: =>
"#{@name} woofs!"
bark: =>
"#{@name} woofs!"
@static = =>
new this('Dog')
@static = =>
new this('Dog')
spark = new Dog('Spark')
fido = new Dog('Fido')
fido.bark = spark.bark
spark = new Dog('Spark')
fido = new Dog('Fido')
fido.bark = spark.bark
ok fido.bark() is 'Spark woofs!'
ok fido.bark() is 'Spark woofs!'
obj = func: Dog.static
obj = func: Dog.static
ok obj.func().name is 'Dog'
ok obj.func().name is 'Dog'
# Testing a bound function in a bound function.
class Mini
num: 10
generate: =>
for i in [1..3]
=>
@num
test "a bound function in a bound function", ->
m = new Mini
eq (func() for func in m.generate()).join(' '), '10 10 10'
class Mini
num: 10
generate: =>
for i in [1..3]
=>
@num
m = new Mini
eq (func() for func in m.generate()).join(' '), '10 10 10'
# Testing a contructor called with varargs.
class Connection
constructor: (one, two, three) ->
[@one, @two, @three] = [one, two, three]
test "contructor called with varargs", ->
out: ->
"#{@one}-#{@two}-#{@three}"
class Connection
constructor: (one, two, three) ->
[@one, @two, @three] = [one, two, three]
list = [3, 2, 1]
conn = new Connection list...
ok conn instanceof Connection
ok conn.out() is '3-2-1'
out: ->
"#{@one}-#{@two}-#{@three}"
list = [3, 2, 1]
conn = new Connection list...
ok conn instanceof Connection
ok conn.out() is '3-2-1'
# Test calling super and passing along all arguments.
class Parent
method: (args...) -> @args = args
test "calling super and passing along all arguments", ->
class Child extends Parent
method: -> super
class Parent
method: (args...) -> @args = args
c = new Child
c.method 1, 2, 3, 4
ok c.args.join(' ') is '1 2 3 4'
class Child extends Parent
method: -> super
c = new Child
c.method 1, 2, 3, 4
ok c.args.join(' ') is '1 2 3 4'
# Test classes wrapped in decorators.
func = (klass) ->
klass::prop = 'value'
klass
test "classes wrapped in decorators", ->
func class Test
prop2: 'value2'
func = (klass) ->
klass::prop = 'value'
klass
ok (new Test).prop is 'value'
ok (new Test).prop2 is 'value2'
func class Test
prop2: 'value2'
ok (new Test).prop is 'value'
ok (new Test).prop2 is 'value2'
# Test anonymous classes.
obj =
klass: class
method: -> 'value'
test "anonymous classes", ->
instance = new obj.klass
ok instance.method() is 'value'
obj =
klass: class
method: -> 'value'
instance = new obj.klass
ok instance.method() is 'value'
# Implicit objects as static properties.
class Static
@static =
one: 1
two: 2
test "Implicit objects as static properties", ->
ok Static.static.one is 1
ok Static.static.two is 2
class Static
@static =
one: 1
two: 2
ok Static.static.one is 1
ok Static.static.two is 2
# Nothing classes.
c = class
ok c instanceof Function
test "nothing classes", ->
c = class
ok c instanceof Function
# Classes with value'd constructors.
counter = 0
classMaker = ->
counter++
inner = counter
->
@value = inner
test "classes with value'd constructors", ->
class One
constructor: classMaker()
counter = 0
classMaker = ->
inner = ++counter
->
@value = inner
class Two
constructor: classMaker()
class One
constructor: classMaker()
ok (new One).value is 1
ok (new Two).value is 2
ok (new One).value is 1
ok (new Two).value is 2
class Two
constructor: classMaker()
eq (new One).value, 1
eq (new Two).value, 2
eq (new One).value, 1
eq (new Two).value, 2
# Exectuable class bodies.
class A
if true
b: 'b'
else
c: 'c'
test "exectuable class bodies", ->
a = new A
class A
if true
b: 'b'
else
c: 'c'
eq a.b, 'b'
eq a.c, undefined
a = new A
eq a.b, 'b'
eq a.c, undefined
# Light metaprogramming.
class Base
@attr: (name) ->
@::[name] = (val) ->
if arguments.length > 0
@["_#{name}"] = val
else
@["_#{name}"]
test "mild metaprogramming", ->
class Robot extends Base
@attr 'power'
@attr 'speed'
class Base
@attr: (name) ->
@::[name] = (val) ->
if arguments.length > 0
@["_#{name}"] = val
else
@["_#{name}"]
robby = new Robot
class Robot extends Base
@attr 'power'
@attr 'speed'
ok robby.power() is undefined
robby = new Robot
robby.power 11
robby.speed Infinity
ok robby.power() is undefined
eq robby.power(), 11
eq robby.speed(), Infinity
robby.power 11
robby.speed Infinity
eq robby.power(), 11
eq robby.speed(), Infinity
# Namespaced classes do not reserve their function name in outside scope.
one = {}
two = {}
test "namespaced classes do not reserve their function name in outside scope", ->
class one.Klass
@label = "one"
one = {}
two = {}
class two.Klass
@label = "two"
class one.Klass
@label = "one"
eq typeof Klass, 'undefined'
eq one.Klass.label, 'one'
eq two.Klass.label, 'two'
class two.Klass
@label = "two"
eq typeof Klass, 'undefined'
eq one.Klass.label, 'one'
eq two.Klass.label, 'two'
# Nested classes.
class Outer
constructor: ->
@label = 'outer'
test "nested classes", ->
class @Inner
class Outer
constructor: ->
@label = 'inner'
@label = 'outer'
eq (new Outer).label, 'outer'
eq (new Outer.Inner).label, 'inner'
class @Inner
constructor: ->
@label = 'inner'
eq (new Outer).label, 'outer'
eq (new Outer.Inner).label, 'inner'
# Variables in constructor bodies are correctly scoped.
class A
x = 1
constructor: ->
x = 10
y = 20
y = 2
captured: ->
{x, y}
test "variables in constructor bodies are correctly scoped", ->
a = new A
eq a.captured().x, 10
eq a.captured().y, 2
class A
x = 1
constructor: ->
x = 10
y = 20
y = 2
captured: ->
{x, y}
a = new A
eq a.captured().x, 10
eq a.captured().y, 2
# Issue #924: Static methods in nested classes.
class A
@B: class
@c = -> 5
test "Issue #924: Static methods in nested classes", ->
eq A.B.c(), 5
class A
@B: class
@c = -> 5
eq A.B.c(), 5
# `class extends this` ...
class A
func: -> 'A'
test "`class extends this`", ->
B = null
makeClass = ->
B = class extends this
func: -> super + ' B'
class A
func: -> 'A'
makeClass.call A
B = null
makeClass = ->
B = class extends this
func: -> super + ' B'
eq (new B()).func(), 'A B'
makeClass.call A
eq (new B()).func(), 'A B'
test "ensure that constructors invoked with splats return a new object", ->
args = [1, 2, 3]
Type = (@args) ->
type = new Type args
ok type and type instanceof Type
ok type.args and type.args instanceof Array
ok v is args[i] for v, i in type.args
Type1 = (@a, @b, @c) ->
type1 = new Type1 args...
ok type1 instanceof Type1
eq type1.constructor, Type1
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
# Ensure that constructors invoked with splats cache the function.
called = 0
get = -> if called++ then false else class Type
new get() args...
test "`new` shouldn't add extra parens", ->
ok new Date().constructor is Date
# Ensure that constructors invoked with splats return a new object.
args = [1, 2, 3]
Type = (@args) ->
type = new Type args
test "`new` works against bare function", ->
ok type and type instanceof Type
ok type.args and type.args instanceof Array
ok v is args[i] for v, i in type.args
eq Date, new ->
eq this, new => this
Date
Type1 = (@a, @b, @c) ->
type1 = new Type1 args...
ok type1 instanceof Type1
eq type1.constructor, Type1
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
test "#1182: a subclass should be able to set its constructor to an external function", ->
ctor = ->
@val = 1
class A
class B extends A
constructor: ctor
eq (new B).val, 1
# Ensure that constructors invoked with splats cache the function.
called = 0
get = -> if called++ then false else class Type
new get() args...
test "#1182: external constructors continued", ->
ctor = ->
class A
class B extends A
method: ->
constructor: ctor
ok B::method
# `new` shouldn't add extra parens
ok new Date().constructor is Date
test "#1313: misplaced __extends", ->
nonce = {}
class A
class B extends A
prop: nonce
constructor: ->
eq nonce, B::prop
# `new` works against bare function
eq Date, new ->
eq this, new => this
Date
test "#1182: execution order needs to be considered as well", ->
counter = 0
makeFn = (n) -> eq n, ++counter; ->
class B extends (makeFn 1)
@B: makeFn 2
constructor: makeFn 3
test "#1182: external constructors with bound functions", ->
fn = ->
{one: 1}
class B
class A
constructor: fn
method: => this instanceof A
ok (new A).method.call(new B)

View File

@@ -1,4 +0,0 @@
# Command
# -------
# TODO: add tests

View File

@@ -110,7 +110,7 @@ test "spaced comments with conditional statements", ->
eq nonce, result
#### Block Comments
# Block Comments
###
This is a here-comment.

View File

@@ -1,47 +1,43 @@
# Compilation
# -----------
# TODO: refactor compilation tests
# helper to assert that a string should fail compilation
cantCompile = (code) ->
throws -> CoffeeScript.compile code
# Ensure that carriage returns don't break compilation on Windows.
doesNotThrow -> CoffeeScript.compile 'one\r\ntwo', bare: on
test "ensure that carriage returns don't break compilation on Windows", ->
doesNotThrow -> CoffeeScript.compile 'one\r\ntwo', bare: on
# `globals: on` removes `var`s
eq -1, CoffeeScript.compile('x = y', bare: on, globals: on).indexOf 'var'
test "--bare", ->
eq -1, CoffeeScript.compile('x = y', bare: on).indexOf 'function'
ok 'passed' is CoffeeScript.eval '"passed"', bare: on, filename: 'test'
ok 'passed' is CoffeeScript.eval '"passed"', bare: on, filename: 'test'
# multiple generated references
(->
test "multiple generated references", ->
a = {b: []}
a.b[true] = -> this == a.b
c = 0
d = []
ok a.b[0<++c<2] d...
)()
# Splat on a line by itself is invalid.
cantCompile "x 'a'\n...\n"
test "splat on a line by itself is invalid", ->
cantCompile "x 'a'\n...\n"
#750
cantCompile 'f(->'
test "Issue 750", ->
cantCompile 'a = (break)'
cantCompile 'f(->'
cantCompile 'a = (return 5 for item in list)'
cantCompile 'a = (break)'
cantCompile 'a = (return 5 while condition)'
cantCompile 'a = (return 5 for item in list)'
cantCompile 'a = for x in y\n return 5'
cantCompile 'a = (return 5 while condition)'
# Issue #986: Unicode identifiers.
λ = 5
eq λ, 5
cantCompile 'a = for x in y\n return 5'
test "Issue #986: Unicode identifiers", ->
λ = 5
eq λ, 5
test "don't accidentally stringify keywords", ->
ok (-> this == 'this')() is false
@@ -55,3 +51,11 @@ test "#1026", ->
else
d
'''
test "#1050", ->
cantCompile "### */ ###"
test "#1106: __proto__ compilation", ->
object = eq
@["__proto__"] = true
ok __proto__

View File

@@ -9,323 +9,357 @@
# TODO: refactor comprehension tests
# Basic array comprehensions.
nums = (n * n for n in [1, 2, 3] when n & 1)
results = (n * 2 for n in nums)
test "Basic array comprehensions.", ->
ok results.join(',') is '2,18'
nums = (n * n for n in [1, 2, 3] when n & 1)
results = (n * 2 for n in nums)
ok results.join(',') is '2,18'
# Basic object comprehensions.
obj = {one: 1, two: 2, three: 3}
names = (prop + '!' for prop of obj)
odds = (prop + '!' for prop, value of obj when value & 1)
test "Basic object comprehensions.", ->
ok names.join(' ') is "one! two! three!"
ok odds.join(' ') is "one! three!"
obj = {one: 1, two: 2, three: 3}
names = (prop + '!' for prop of obj)
odds = (prop + '!' for prop, value of obj when value & 1)
ok names.join(' ') is "one! two! three!"
ok odds.join(' ') is "one! three!"
# Basic range comprehensions.
nums = (i * 3 for i in [1..3])
test "Basic range comprehensions.", ->
negs = (x for x in [-20..-5*2])
negs = negs[0..2]
nums = (i * 3 for i in [1..3])
result = nums.concat(negs).join(', ')
negs = (x for x in [-20..-5*2])
negs = negs[0..2]
ok result is '3, 6, 9, -20, -19, -18'
result = nums.concat(negs).join(', ')
ok result is '3, 6, 9, -20, -19, -18'
# With range comprehensions, you can loop in steps.
results = (x for x in [0...15] by 5)
ok results.join(' ') is '0 5 10'
test "With range comprehensions, you can loop in steps.", ->
results = (x for x in [0..100] by 10)
ok results.join(' ') is '0 10 20 30 40 50 60 70 80 90 100'
results = (x for x in [0...15] by 5)
ok results.join(' ') is '0 5 10'
results = (x for x in [0..100] by 10)
ok results.join(' ') is '0 10 20 30 40 50 60 70 80 90 100'
# And can loop downwards, with a negative step.
results = (x for x in [5..1])
test "And can loop downwards, with a negative step.", ->
ok results.join(' ') is '5 4 3 2 1'
ok results.join(' ') is [(10-5)..(-2+3)].join(' ')
results = (x for x in [5..1])
results = (x for x in [10..1])
ok results.join(' ') is [10..1].join(' ')
ok results.join(' ') is '5 4 3 2 1'
ok results.join(' ') is [(10-5)..(-2+3)].join(' ')
results = (x for x in [10...0] by -2)
ok results.join(' ') is [10, 8, 6, 4, 2].join(' ')
results = (x for x in [10..1])
ok results.join(' ') is [10..1].join(' ')
results = (x for x in [10...0] by -2)
ok results.join(' ') is [10, 8, 6, 4, 2].join(' ')
# Range comprehension gymnastics.
eq "#{i for i in [5..1]}", '5,4,3,2,1'
eq "#{i for i in [5..-5] by -5}", '5,0,-5'
test "Range comprehension gymnastics.", ->
a = 6
b = 0
c = -2
eq "#{i for i in [5..1]}", '5,4,3,2,1'
eq "#{i for i in [5..-5] by -5}", '5,0,-5'
eq "#{i for i in [a..b]}", '6,5,4,3,2,1,0'
eq "#{i for i in [a..b] by c}", '6,4,2,0'
a = 6
b = 0
c = -2
eq "#{i for i in [a..b]}", '6,5,4,3,2,1,0'
eq "#{i for i in [a..b] by c}", '6,4,2,0'
# Multiline array comprehension with filter.
evens = for num in [1, 2, 3, 4, 5, 6] when not (num & 1)
num *= -1
num -= 2
num * -1
eq evens + '', '4,6,8'
test "Multiline array comprehension with filter.", ->
evens = for num in [1, 2, 3, 4, 5, 6] when not (num & 1)
num *= -1
num -= 2
num * -1
eq evens + '', '4,6,8'
# The in operator still works, standalone.
ok 2 of evens
test "The in operator still works, standalone.", ->
# all isn't reserved.
all = 1
ok 2 of evens
# Ensure that the closure wrapper preserves local variables.
obj = {}
test "all isn't reserved.", ->
for method in ['one', 'two', 'three'] then do (method) ->
obj[method] = ->
"I'm " + method
ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
all = 1
# Index values at the end of a loop.
i = 0
for i in [1..3]
-> 'func'
break if false
ok i is 4
test "Ensure that the closure wrapper preserves local variables.", ->
obj = {}
for method in ['one', 'two', 'three'] then do (method) ->
obj[method] = ->
"I'm " + method
ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
# Ensure that local variables are closed over for range comprehensions.
funcs = for i in [1..3]
do (i) ->
-> -i
test "Index values at the end of a loop.", ->
eq (func() for func in funcs).join(' '), '-1 -2 -3'
ok i is 4
i = 0
for i in [1..3]
-> 'func'
break if false
ok i is 4
# Even when referenced in the filter.
list = ['one', 'two', 'three']
test "Ensure that local variables are closed over for range comprehensions.", ->
methods = for num, i in list when num isnt 'two' and i isnt 1
do (num, i) ->
-> num + ' ' + i
ok methods.length is 2
ok methods[0]() is 'one 0'
ok methods[1]() is 'three 2'
# Even a convoluted one.
funcs = []
for i in [1..3]
do (i) ->
x = i * 2
((z)->
funcs.push -> z + ' ' + i
)(x)
ok (func() for func in funcs).join(', ') is '2 1, 4 2, 6 3'
funcs = []
results = for i in [1..3]
do (i) ->
z = (x * 3 for x in [1..i])
((a, b, c) -> [a, b, c].join(' ')).apply this, z
ok results.join(', ') is '3 , 3 6 , 3 6 9'
# Naked ranges are expanded into arrays.
array = [0..10]
ok(num % 2 is 0 for num in array by 2)
# Nested shared scopes.
foo = ->
for i in [0..7]
funcs = for i in [1..3]
do (i) ->
for j in [0..7]
do (j) ->
-> i + j
-> -i
eq foo()[3][4](), 7
eq (func() for func in funcs).join(' '), '-1 -2 -3'
ok i is 4
# Scoped loop pattern matching.
a = [[0], [1]]
funcs = []
test "Even when referenced in the filter.", ->
for [v] in a
do (v) ->
funcs.push -> v
list = ['one', 'two', 'three']
eq funcs[0](), 0
eq funcs[1](), 1
methods = for num, i in list when num isnt 'two' and i isnt 1
do (num, i) ->
-> num + ' ' + i
ok methods.length is 2
ok methods[0]() is 'one 0'
ok methods[1]() is 'three 2'
# Nested comprehensions.
multiLiner =
for x in [3..5]
for y in [3..5]
[x, y]
test "Even a convoluted one.", ->
singleLiner =
(([x, y] for y in [3..5]) for x in [3..5])
funcs = []
ok multiLiner.length is singleLiner.length
ok 5 is multiLiner[2][2][1]
ok 5 is singleLiner[2][2][1]
for i in [1..3]
do (i) ->
x = i * 2
((z)->
funcs.push -> z + ' ' + i
)(x)
ok (func() for func in funcs).join(', ') is '2 1, 4 2, 6 3'
funcs = []
results = for i in [1..3]
do (i) ->
z = (x * 3 for x in [1..i])
((a, b, c) -> [a, b, c].join(' ')).apply this, z
ok results.join(', ') is '3 , 3 6 , 3 6 9'
# Comprehensions within parentheses.
result = null
store = (obj) -> result = obj
store (x * 2 for x in [3, 2, 1])
test "Naked ranges are expanded into arrays.", ->
ok result.join(' ') is '6 4 2'
array = [0..10]
ok(num % 2 is 0 for num in array by 2)
# Closure-wrapped comprehensions that refer to the "arguments" object.
expr = ->
result = (item * item for item in arguments)
test "Nested shared scopes.", ->
ok expr(2, 4, 8).join(' ') is '4 16 64'
foo = ->
for i in [0..7]
do (i) ->
for j in [0..7]
do (j) ->
-> i + j
eq foo()[3][4](), 7
# Fast object comprehensions over all properties, including prototypal ones.
class Cat
constructor: -> @name = 'Whiskers'
breed: 'tabby'
hair: 'cream'
test "Scoped loop pattern matching.", ->
whiskers = new Cat
own = (value for own key, value of whiskers)
all = (value for key, value of whiskers)
a = [[0], [1]]
funcs = []
ok own.join(' ') is 'Whiskers'
ok all.sort().join(' ') is 'Whiskers cream tabby'
for [v] in a
do (v) ->
funcs.push -> v
eq funcs[0](), 0
eq funcs[1](), 1
# Optimized range comprehensions.
exxes = ('x' for [0...10])
ok exxes.join(' ') is 'x x x x x x x x x x'
test "Nested comprehensions.", ->
multiLiner =
for x in [3..5]
for y in [3..5]
[x, y]
singleLiner =
(([x, y] for y in [3..5]) for x in [3..5])
ok multiLiner.length is singleLiner.length
ok 5 is multiLiner[2][2][1]
ok 5 is singleLiner[2][2][1]
# Comprehensions safely redeclare parameters if they're not present in closest
# scope.
rule = (x) -> x
test "Comprehensions within parentheses.", ->
learn = ->
rule for rule in [1, 2, 3]
result = null
store = (obj) -> result = obj
store (x * 2 for x in [3, 2, 1])
ok learn().join(' ') is '1 2 3'
ok rule(101) is 101
f = -> [-> ok no, 'should cache source']
ok yes for k of [f] = f()
ok result.join(' ') is '6 4 2'
# Lenient on pure statements not trying to reach out of the closure
val = for i in [1]
for j in [] then break
i
ok val[0] is i
test "Closure-wrapped comprehensions that refer to the 'arguments' object.", ->
expr = ->
result = (item * item for item in arguments)
ok expr(2, 4, 8).join(' ') is '4 16 64'
# Comprehensions only wrap their last line in a closure, allowing other lines
# to have pure expressions in them.
func = -> for i in [1]
break if i is 2
j for j in [1]
test "Fast object comprehensions over all properties, including prototypal ones.", ->
ok func()[0][0] is 1
class Cat
constructor: -> @name = 'Whiskers'
breed: 'tabby'
hair: 'cream'
i = 6
odds = while i--
continue unless i & 1
i
whiskers = new Cat
own = (value for own key, value of whiskers)
all = (value for key, value of whiskers)
ok odds.join(', ') is '5, 3, 1'
ok own.join(' ') is 'Whiskers'
ok all.sort().join(' ') is 'Whiskers cream tabby'
# Issue #897: Ensure that plucked function variables aren't leaked.
facets = {}
list = ['one', 'two']
test "Optimized range comprehensions.", ->
(->
for entity in list
facets[entity] = -> entity
)()
eq typeof entity, 'undefined'
eq facets['two'](), 'two'
exxes = ('x' for [0...10])
ok exxes.join(' ') is 'x x x x x x x x x x'
# Issue #905. Soaks as the for loop subject.
a = {b: {c: [1, 2, 3]}}
for d in a.b?.c
e = d
test "Comprehensions safely redeclare parameters if they're not present in closest scope.", ->
eq e, 3
rule = (x) -> x
learn = ->
rule for rule in [1, 2, 3]
ok learn().join(' ') is '1 2 3'
ok rule(101) is 101
f = -> [-> ok no, 'should cache source']
ok yes for k of [f] = f()
# Issue #948. Capturing loop variables.
funcs = []
list = ->
[1, 2, 3]
test "Lenient on pure statements not trying to reach out of the closure", ->
for y in list()
do (y) ->
z = y
funcs.push -> "y is #{y} and z is #{z}"
eq funcs[1](), "y is 2 and z is 2"
val = for i in [1]
for j in [] then break
i
ok val[0] is i
# Cancel the comprehension if there's a jump inside the loop.
result = try
for i in [0...10]
continue if i < 5
i
test "Comprehensions only wrap their last line in a closure, allowing other lines
to have pure expressions in them.", ->
eq result, 10
func = -> for i in [1]
break if i is 2
j for j in [1]
ok func()[0][0] is 1
i = 6
odds = while i--
continue unless i & 1
i
ok odds.join(', ') is '5, 3, 1'
# Comprehensions over break.
arrayEq (break for [1..10]), []
test "Issue #897: Ensure that plucked function variables aren't leaked.", ->
# Comprehensions over continue.
arrayEq (break for [1..10]), []
facets = {}
list = ['one', 'two']
(->
for entity in list
facets[entity] = -> entity
)()
eq typeof entity, 'undefined'
eq facets['two'](), 'two'
# Comprehensions over function literals.
a = 0
for f in [-> a = 1]
do (f) ->
do f
test "Issue #905. Soaks as the for loop subject.", ->
eq a, 1
a = {b: {c: [1, 2, 3]}}
for d in a.b?.c
e = d
eq e, 3
# Comprehensions that mention arguments.
list = [arguments: 10]
args = for f in list
do (f) ->
f.arguments
eq args[0], 10
test "Issue #948. Capturing loop variables.", ->
funcs = []
list = ->
[1, 2, 3]
for y in list()
do (y) ->
z = y
funcs.push -> "y is #{y} and z is #{z}"
eq funcs[1](), "y is 2 and z is 2"
test "Cancel the comprehension if there's a jump inside the loop.", ->
result = try
for i in [0...10]
continue if i < 5
i
eq result, 10
test "Comprehensions over break.", ->
arrayEq (break for [1..10]), []
test "Comprehensions over continue.", ->
arrayEq (continue for [1..10]), []
test "Comprehensions over function literals.", ->
a = 0
for f in [-> a = 1]
do (f) ->
do f
eq a, 1
test "Comprehensions that mention arguments.", ->
list = [arguments: 10]
args = for f in list
do (f) ->
f.arguments
eq args[0], 10
test "expression conversion under explicit returns", ->
@@ -341,8 +375,6 @@ test "expression conversion under explicit returns", ->
arrayEq [nonce,nonce,nonce], fn()
#### Implicit Destructuring Assignment
test "implicit destructuring assignment in object of objects", ->
a={}; b={}; c={}
obj = {
@@ -353,6 +385,7 @@ test "implicit destructuring assignment in object of objects", ->
result = ([y,z] for y, { d: z } of obj)
arrayEq [['a',a],['b',b],['c',c]], result
test "implicit destructuring assignment in array of objects", ->
a={}; b={}; c={}; d={}; e={}; f={}
arr = [
@@ -363,8 +396,35 @@ test "implicit destructuring assignment in array of objects", ->
result = ([y,z] for { a: y, b: { c: z } } in arr)
arrayEq [[a,b],[c,d],[e,f]], result
test "implicit destructuring assignment in array of arrays", ->
a={}; b={}; c={}; d={}; e={}; f={}
arr = [[a, [b]], [c, [d]], [e, [f]]]
result = ([y,z] for [y, [z]] in arr)
arrayEq [[a,b],[c,d],[e,f]], result
test "issue #1124: don't assign a variable in two scopes", ->
lista = [1, 2, 3, 4, 5]
listb = (_i + 1 for _i in lista)
arrayEq [2, 3, 4, 5, 6], listb
test "#1326: `by` value is uncached", ->
a = [0,1,2]
fi = gi = hi = 0
f = -> ++fi
g = -> ++gi
h = -> ++hi
forCompile = []
rangeCompileSimple = []
#exercises For.compile
for v,i in a by f() then forCompile.push i
#exercises Range.compileSimple
rangeCompileSimple = (i for i in [0..2] by g())
arrayEq a, forCompile
arrayEq a, rangeCompileSimple
#exercises Range.compile
eq "#{i for i in [0..2] by h()}", '0,1,2'

View File

@@ -14,7 +14,7 @@
# shared identity function
id = (_) -> if arguments.length is 1 then _ else Array::slice.call(arguments)
#### Conditionals
# Conditionals
test "basic conditionals", ->
if false
@@ -198,38 +198,38 @@ test "#748: trailing reserved identifiers", ->
eq nonce, result
#### For / While / Until / Loop
test "basic `while` loops", ->
# TODO: refactor while tests
i = 5
list = while i -= 1
i * 2
ok list.join(' ') is "8 6 4 2"
# While
i = 5
list = (i * 3 while i -= 1)
ok list.join(' ') is "12 9 6 3"
i = 5
list = while i -= 1
i * 2
ok list.join(' ') is "8 6 4 2"
i = 5
func = (num) -> i -= num
assert = -> ok i < 5 > 0
results = while func 1
assert()
i
ok results.join(' ') is '4 3 2 1'
i = 5
list = (i * 3 while i -= 1)
ok list.join(' ') is "12 9 6 3"
i = 10
results = while i -= 1 when i % 2 is 0
i * 2
ok results.join(' ') is '16 12 8 4'
i = 5
func = (num) -> i -= num
assert = -> ok i < 5 > 0
results = while func 1
assert()
i
ok results.join(' ') is '4 3 2 1'
i = 10
results = while i -= 1 when i % 2 is 0
i * 2
ok results.join(' ') is '16 12 8 4'
test "Issue 759: `if` within `while` condition", ->
2 while if 1 then 0
#759: `if` within `while` condition
2 while if 1 then 0
test "assignment inside the condition of a `while` loop", ->
nonce = {}
count = 1
a = nonce while count--
@@ -239,47 +239,45 @@ test "assignment inside the condition of a `while` loop", ->
b = nonce
eq nonce, b
# While over break.
i = 0
result = while i < 10
i++
break
arrayEq result, []
# While over continue.
i = 0
result = while i < 10
i++
continue
arrayEq result, []
test "While over break.", ->
# Until
i = 0
result = while i < 10
i++
break
arrayEq result, []
# TODO: refactor until tests
# TODO: add until tests
value = false
i = 0
results = until value
value = true if i is 5
i++
ok i is 6
test "While over continue.", ->
# Loop
i = 0
result = while i < 10
i++
continue
arrayEq result, []
# TODO: refactor loop tests
# TODO: add loop tests
i = 5
list = []
loop
i -= 1
break if i is 0
list.push i * 2
ok list.join(' ') is '8 6 4 2'
test "Basic `until`", ->
value = false
i = 0
results = until value
value = true if i is 5
i++
ok i is 6
test "Basic `loop`", ->
i = 5
list = []
loop
i -= 1
break if i is 0
list.push i * 2
ok list.join(' ') is '8 6 4 2'
# TODO: refactor for tests
# TODO: add for tests
test "break at the top level", ->
for i in [1,2,3]
@@ -289,7 +287,7 @@ test "break at the top level", ->
eq 2, result
test "break *not* at the top level", ->
someFunc = () ->
someFunc = ->
i = 0
while ++i < 3
result = i
@@ -298,121 +296,125 @@ test "break *not* at the top level", ->
eq 2, someFunc()
#### Switch
test "basic `switch`", ->
# TODO: refactor switch tests
num = 10
result = switch num
when 5 then false
when 'a'
true
true
false
when 10 then true
# Mid-switch comment with whitespace
# and multi line
when 11 then false
else false
ok result
func = (num) ->
switch num
when 2, 4, 6
num = 10
result = switch num
when 5 then false
when 'a'
true
true
when 1, 3, 5
false
ok func(2)
ok func(6)
ok !func(3)
eq func(8), undefined
when 10 then true
# Ensure that trailing switch elses don't get rewritten.
result = false
switch "word"
when "one thing"
doSomething()
else
result = true unless false
# Mid-switch comment with whitespace
# and multi line
when 11 then false
else false
ok result
result = false
switch "word"
when "one thing"
doSomething()
when "other thing"
doSomething()
else
result = true unless false
ok result
ok result
# Should be able to handle switches sans-condition.
result = switch
when null then 0
when !1 then 1
when '' not of {''} then 2
when [] not instanceof Array then 3
when true is false then 4
when 'x' < 'y' > 'z' then 5
when 'a' in ['b', 'c'] then 6
when 'd' in (['e', 'f']) then 7
else ok
func = (num) ->
switch num
when 2, 4, 6
true
when 1, 3, 5
false
eq result, ok
ok func(2)
ok func(6)
ok !func(3)
eq func(8), undefined
# Should be able to use "@properties" within the switch clause.
obj = {
num: 101
func: ->
switch @num
when 101 then '101!'
else 'other'
}
test "Ensure that trailing switch elses don't get rewritten.", ->
ok obj.func() is '101!'
result = false
switch "word"
when "one thing"
doSomething()
else
result = true unless false
ok result
result = false
switch "word"
when "one thing"
doSomething()
when "other thing"
doSomething()
else
result = true unless false
ok result
# Should be able to use "@properties" within the switch cases.
obj = {
num: 101
func: (yesOrNo) ->
result = switch yesOrNo
when yes then @num
else 'other'
result
}
test "Should be able to handle switches sans-condition.", ->
ok obj.func(yes) is 101
result = switch
when null then 0
when !1 then 1
when '' not of {''} then 2
when [] not instanceof Array then 3
when true is false then 4
when 'x' < 'y' > 'z' then 5
when 'a' in ['b', 'c'] then 6
when 'd' in (['e', 'f']) then 7
else ok
eq result, ok
# Switch with break as the return value of a loop.
i = 10
results = while i > 0
i--
switch i % 2
when 1 then i
when 0 then break
test "Should be able to use `@properties` within the switch clause.", ->
eq results.join(', '), '9, , 7, , 5, , 3, , 1, '
obj = {
num: 101
func: ->
switch @num
when 101 then '101!'
else 'other'
}
ok obj.func() is '101!'
# Issue #997. Switch doesn't fallthrough.
val = 1
switch true
when true
if false
return 5
else
val = 2
test "Should be able to use `@properties` within the switch cases.", ->
eq val, 1
obj = {
num: 101
func: (yesOrNo) ->
result = switch yesOrNo
when yes then @num
else 'other'
result
}
ok obj.func(yes) is 101
test "Switch with break as the return value of a loop.", ->
i = 10
results = while i > 0
i--
switch i % 2
when 1 then i
when 0 then break
eq results.join(', '), '9, , 7, , 5, , 3, , 1, '
test "Issue #997. Switch doesn't fallthrough.", ->
val = 1
switch true
when true
if false
return 5
else
val = 2
eq val, 1

View File

@@ -5,13 +5,13 @@
nonce = {}
#### Throw
# Throw
test "basic exception throwing", ->
throws (-> throw 'error'), 'error'
#### Empty Try/Catch/Finally
# Empty Try/Catch/Finally
test "try can exist alone", ->
try
@@ -43,7 +43,7 @@ test "single-line try/catch/finally with empty try, empty catch, empty finally",
try catch err then finally
#### Try/Catch/Finally as an Expression
# Try/Catch/Finally as an Expression
test "return the result of try when no exception is thrown", ->
result = try
@@ -81,7 +81,7 @@ test "optional catch", ->
eq nonce, fn()
#### Try/Catch/Finally Interaction With Other Constructs
# Try/Catch/Finally Interaction With Other Constructs
test "try/catch with empty catch as last statement in a function body", ->
fn = ->

View File

@@ -21,7 +21,7 @@ test "multiple semicolon-separated statements in parentheticals", ->
eq nonce, (1; 2; nonce)
eq nonce, (-> return (1; 2; nonce))()
#### Line Continuation
# Line Continuation
# Property Access
@@ -73,6 +73,18 @@ test "`?.` and `::` should continue lines", ->
#::
#?.foo
doesNotThrow -> CoffeeScript.compile """
oh. yes
oh?. true
oh:: return
"""
doesNotThrow -> CoffeeScript.compile """
a?[b..]
a?[...b]
a?[b..c]
"""
# Array Literals
test "indented array literals don't trigger whitespace rewriting", ->

View File

@@ -7,9 +7,11 @@
# * Explicit Returns
# shared identity function
id = (_) -> if arguments.length is 1 then _ else Array::slice.call(arguments)
id = (_) -> if arguments.length is 1 then _ else [arguments...]
test "basic argument passing", ->
a = {}
b = {}
c = {}
@@ -18,7 +20,9 @@ test "basic argument passing", ->
eq a, (id a)
eq c, (id a, b, c)[2]
test "passing arguments on separate lines", ->
a = {}
b = {}
c = {}
@@ -37,7 +41,9 @@ test "passing arguments on separate lines", ->
eq b,
(id b)
test "optional parens can be used in a nested fashion", ->
call = (func) -> func()
add = (a,b) -> a + b
result = call ->
@@ -45,7 +51,9 @@ test "optional parens can be used in a nested fashion", ->
add 5, 5
ok result is 10
test "hanging commas and semicolons in argument list", ->
fn = () -> arguments.length
eq 2, fn(0,1,)
eq 3, fn 0, 1,
@@ -58,24 +66,32 @@ test "hanging commas and semicolons in argument list", ->
throws -> CoffeeScript.compile "fn(,0)"
throws -> CoffeeScript.compile "fn(;0)"
func = ->
return if true
eq undefined, func()
result = ("hello".slice) 3
ok result is 'lo'
test "function invocation", ->
# And even with strange things like this:
funcs = [((x) -> x), ((x) -> x * x)]
result = funcs[1] 5
ok result is 25
func = ->
return if true
eq undefined, func()
# More fun with optional parens.
fn = (arg) -> arg
ok fn(fn {prop: 101}).prop is 101
result = ("hello".slice) 3
ok result is 'lo'
test "And even with strange things like this:", ->
funcs = [((x) -> x), ((x) -> x * x)]
result = funcs[1] 5
ok result is 25
test "More fun with optional parens.", ->
fn = (arg) -> arg
ok fn(fn {prop: 101}).prop is 101
okFunc = (f) -> ok(f())
okFunc -> true
okFunc = (f) -> ok(f())
okFunc -> true
test "chained function calls", ->
nonce = {}
@@ -84,31 +100,39 @@ test "chained function calls", ->
eq nonce, identityWrap(identityWrap(nonce))()()
eq nonce, (identityWrap identityWrap nonce)()()
# Multi-blocks with optional parens.
result = fn( ->
fn ->
"Wrapped"
)
ok result()() is 'Wrapped'
# method calls
fnId = (fn) -> -> fn.apply this, arguments
math = {
add: (a, b) -> a + b
anonymousAdd: (a, b) -> a + b
fastAdd: fnId (a, b) -> a + b
}
ok math.add(5, 5) is 10
ok math.anonymousAdd(10, 10) is 20
ok math.fastAdd(20, 20) is 40
test "Multi-blocks with optional parens.", ->
fn = (arg) -> arg
result = fn( ->
fn ->
"Wrapped"
)
ok result()() is 'Wrapped'
test "method calls", ->
fnId = (fn) -> -> fn.apply this, arguments
math = {
add: (a, b) -> a + b
anonymousAdd: (a, b) -> a + b
fastAdd: fnId (a, b) -> a + b
}
ok math.add(5, 5) is 10
ok math.anonymousAdd(10, 10) is 20
ok math.fastAdd(20, 20) is 40
test "Ensure that functions can have a trailing comma in their argument list", ->
mult = (x, mids..., y) ->
x *= n for n in mids
x *= y
ok mult(1, 2,) is 2
ok mult(1, 2, 3,) is 6
ok mult(10, (i for i in [1..6])...) is 7200
# Ensure that functions can have a trailing comma in their argument list
mult = (x, mids..., y) ->
x *= n for n in mids
x *= y
ok mult(1, 2,) is 2
ok mult(1, 2, 3,) is 6
ok mult(10, (i for i in [1..6])...) is 7200
test "`@` and `this` should both be able to invoke a method", ->
nonce = {}
@@ -118,136 +142,170 @@ test "`@` and `this` should both be able to invoke a method", ->
fn.withAt()
fn.withThis()
# Trying an implicit object call with a trailing function.
a = null
meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
meth 'apple', b: 1, a: 13, ->
'orange'
ok a is '13 apple orange'
# Ensure that empty functions don't return mistaken values.
obj =
func: (@param, @rest...) ->
ok obj.func(101, 102, 103, 104) is undefined
ok obj.param is 101
ok obj.rest.join(' ') is '102 103 104'
test "Trying an implicit object call with a trailing function.", ->
# Passing multiple functions without paren-wrapping is legal, and should compile.
sum = (one, two) -> one() + two()
result = sum ->
7 + 9
, ->
1 + 3
ok result is 20
a = null
meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
meth 'apple', b: 1, a: 13, ->
'orange'
ok a is '13 apple orange'
# Implicit call with a trailing if statement as a param.
func = -> arguments[1]
result = func 'one', if false then 100 else 13
ok result is 13
# Test more function passing:
result = sum( ->
1 + 2
, ->
2 + 1
)
ok result is 6
test "Ensure that empty functions don't return mistaken values.", ->
sum = (a, b) -> a + b
result = sum(1
, 2)
ok result is 3
obj =
func: (@param, @rest...) ->
ok obj.func(101, 102, 103, 104) is undefined
ok obj.param is 101
ok obj.rest.join(' ') is '102 103 104'
# Chained blocks, with proper indentation levels:
counter =
results: []
tick: (func) ->
@results.push func()
this
counter
.tick ->
3
.tick ->
2
.tick ->
1
arrayEq [3,2,1], counter.results
# This is a crazy one.
x = (obj, func) -> func obj
ident = (x) -> x
result = x {one: ident 1}, (obj) ->
inner = ident(obj)
ident inner
ok result.one is 1
test "Passing multiple functions without paren-wrapping is legal, and should compile.", ->
# More paren compilation tests:
reverse = (obj) -> obj.reverse()
ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
sum = (one, two) -> one() + two()
result = sum ->
7 + 9
, ->
1 + 3
ok result is 20
# Test for inline functions with parentheses and implicit calls.
combine = (func, num) -> func() * num
result = combine (-> 1 + 2), 3
ok result is 9
# Test for calls/parens/multiline-chains.
f = (x) -> x
result = (f 1).toString()
.length
ok result is 1
test "Implicit call with a trailing if statement as a param.", ->
# Test implicit calls in functions in parens:
result = ((val) ->
[].push val
val
)(10)
ok result is 10
func = -> arguments[1]
result = func 'one', if false then 100 else 13
ok result is 13
# Ensure that chained calls with indented implicit object literals below are
# alright.
result = null
obj =
method: (val) -> this
second: (hash) -> result = hash.three
obj
.method(
101
).second(
one:
two: 2
three: 3
test "Test more function passing:", ->
sum = (one, two) -> one() + two()
result = sum( ->
1 + 2
, ->
2 + 1
)
eq result, 3
ok result is 6
# Test newline-supressed call chains with nested functions.
obj =
call: -> this
func = ->
sum = (a, b) -> a + b
result = sum(1
, 2)
ok result is 3
test "Chained blocks, with proper indentation levels:", ->
counter =
results: []
tick: (func) ->
@results.push func()
this
counter
.tick ->
3
.tick ->
2
.tick ->
1
arrayEq [3,2,1], counter.results
test "This is a crazy one.", ->
x = (obj, func) -> func obj
ident = (x) -> x
result = x {one: ident 1}, (obj) ->
inner = ident(obj)
ident inner
ok result.one is 1
test "More paren compilation tests:", ->
reverse = (obj) -> obj.reverse()
ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
test "Test for inline functions with parentheses and implicit calls.", ->
combine = (func, num) -> func() * num
result = combine (-> 1 + 2), 3
ok result is 9
test "Test for calls/parens/multiline-chains.", ->
f = (x) -> x
result = (f 1).toString()
.length
ok result is 1
test "Test implicit calls in functions in parens:", ->
result = ((val) ->
[].push val
val
)(10)
ok result is 10
test "Ensure that chained calls with indented implicit object literals below are alright.", ->
result = null
obj =
method: (val) -> this
second: (hash) -> result = hash.three
obj
.call ->
one two
.call ->
three four
101
eq func(), 101
.method(
101
).second(
one:
two: 2
three: 3
)
eq result, 3
# Implicit objects with number arguments.
func = (x, y) -> y
obj =
prop: func "a", 1
ok obj.prop is 1
# Non-spaced unary and binary operators should cause a function call.
func = (val) -> val + 1
ok (func +5) is 6
ok (func -5) is -4
test "Test newline-supressed call chains with nested functions.", ->
# Prefix unary assignment operators are allowed in parenless calls.
val = 5
ok (func --val) is 5
obj =
call: -> this
func = ->
obj
.call ->
one two
.call ->
three four
101
eq func(), 101
test "Implicit objects with number arguments.", ->
func = (x, y) -> y
obj =
prop: func "a", 1
ok obj.prop is 1
test "Non-spaced unary and binary operators should cause a function call.", ->
func = (val) -> val + 1
ok (func +5) is 6
ok (func -5) is -4
test "Prefix unary assignment operators are allowed in parenless calls.", ->
func = (val) -> val + 1
val = 5
ok (func --val) is 5
test "#855: execution context for `func arr...` should be `null`", ->
contextTest = -> eq @, global
contextTest = -> eq @, if window? then window else global
array = []
contextTest array
contextTest.apply null, array
@@ -262,13 +320,14 @@ test "#904: Destructuring function arguments with same-named variables in scope"
eq nonce, a
eq nonce, b
obj =
index: 0
0: {method: -> this is obj[0]}
ok obj[obj.index++].method([]...), 'should cache base value'
test "caching base value", ->
obj =
index: 0
0: {method: -> this is obj[0]}
ok obj[obj.index++].method([]...)
#### Splats in Function Invocations
test "passing splats to functions", ->
arrayEq [0..4], id id [0..4]...
@@ -280,33 +339,46 @@ test "passing splats to functions", ->
arrayEq [2..6], others
eq 7, last
#894: Splatting against constructor-chained functions.
x = null
class Foo
bar: (y) -> x = y
new Foo().bar([101]...)
eq x, 101
test "splat variables are local to the function", ->
outer = "x"
clobber = (avar, outer...) -> outer
clobber "foo", "bar"
eq "x", outer
# Functions with splats being called with too few arguments.
pen = null
method = (first, variable..., penultimate, ultimate) ->
pen = penultimate
method 1, 2, 3, 4, 5, 6, 7, 8, 9
ok pen is 8
method 1, 2, 3
ok pen is 2
method 1, 2
ok pen is 2
# splats with super() within classes.
class Parent
meth: (args...) ->
args
class Child extends Parent
meth: ->
nums = [3, 2, 1]
super nums...
ok (new Child).meth().join(' ') is '3 2 1'
test "Issue 894: Splatting against constructor-chained functions.", ->
x = null
class Foo
bar: (y) -> x = y
new Foo().bar([101]...)
eq x, 101
test "Functions with splats being called with too few arguments.", ->
pen = null
method = (first, variable..., penultimate, ultimate) ->
pen = penultimate
method 1, 2, 3, 4, 5, 6, 7, 8, 9
ok pen is 8
method 1, 2, 3
ok pen is 2
method 1, 2
ok pen is 2
test "splats with super() within classes.", ->
class Parent
meth: (args...) ->
args
class Child extends Parent
meth: ->
nums = [3, 2, 1]
super nums...
ok (new Child).meth().join(' ') is '3 2 1'
test "#1011: passing a splat to a method of a number", ->
eq '1011', 11.toString [2]...
@@ -315,12 +387,13 @@ test "#1011: passing a splat to a method of a number", ->
eq '1011', (131.0).toString [5]...
#### Implicit Return
test "implicit return", ->
eq ok, new ->
ok
### Should `return` implicitly ###
### even with trailing comments. ###
eq ok, new ->
ok
### Should `return` implicitly ###
### even with trailing comments. ###
test "implicit returns with multiple branches", ->
nonce = {}
@@ -332,6 +405,7 @@ test "implicit returns with multiple branches", ->
nonce
eq nonce, fn()
test "implicit returns with switches", ->
nonce = {}
fn = ->
@@ -340,6 +414,7 @@ test "implicit returns with switches", ->
else return undefined
eq nonce, fn()
test "preserve context when generating closure wrappers for expression conversions", ->
nonce = {}
obj =
@@ -355,12 +430,16 @@ test "preserve context when generating closure wrappers for expression conversio
eq nonce, obj.property
#### Explicit Returns
test "don't wrap \"pure\" statements in a closure", ->
test "don't wrap 'pure' statements in a closure", ->
nonce = {}
items = [0, 1, 2, 3, nonce, 4, 5]
fn = (items) ->
for item in items
return item if item is nonce
eq nonce, fn items
#### Unusual `new` Usage
test "usage of `new` is careful about where the invocation parens end up", ->
eq 'object', typeof new try Array
eq 'object', typeof new do -> ->

View File

@@ -11,7 +11,7 @@
# * Parameter Destructuring
# * Default Parameters
#### Function Definition
# Function Definition
x = 1
y = {}
@@ -46,7 +46,7 @@ del = -> 5
ok del() is 5
#### Bound Function Definition
# Bound Function Definition
obj =
bound: ->
@@ -64,7 +64,15 @@ ok obj isnt obj.unbound()
eq obj, obj.nested()
#### Parameter List Features
test "self-referencing functions", ->
changeMe = ->
changeMe = 2
changeMe()
eq changeMe, 2
# Parameter List Features
test "splats", ->
arrayEq [0, 1, 2], (((splat...) -> splat) 0, 1, 2)
@@ -147,3 +155,11 @@ test "default values with splatted arguments", ->
eq 5, withSplats(1,1)
eq 1, withSplats(1,1,1)
eq 2, withSplats(1,1,1,1)
test "default values with function calls", ->
doesNotThrow -> CoffeeScript.compile "(x = f()) ->"
test "arguments vs parameters", ->
doesNotThrow -> CoffeeScript.compile "f(x) ->"
f = (g) -> g()
eq 5, f (x) -> 5

View File

@@ -5,7 +5,7 @@
{starts, ends, compact, count, merge, extend, flatten, del, last} = CoffeeScript.helpers
#### `starts`
# `starts`
test "the `starts` helper tests if a string starts with another string", ->
ok starts('01234', '012')
@@ -16,7 +16,7 @@ test "the `starts` helper can take an optional offset", ->
ok not starts('01234', '01', 1)
#### `ends`
# `ends`
test "the `ends` helper tests if a string ends with another string", ->
ok ends('01234', '234')
@@ -27,7 +27,7 @@ test "the `ends` helper can take an optional offset", ->
ok not ends('01234', '234', 6)
#### `compact`
# `compact`
test "the `compact` helper removes falsey values from an array, preserves truthy ones", ->
allValues = [1, 0, false, obj={}, [], '', ' ', -1, null, undefined, true]
@@ -35,7 +35,7 @@ test "the `compact` helper removes falsey values from an array, preserves truthy
arrayEq truthyValues, compact(allValues)
#### `count`
# `count`
test "the `count` helper counts the number of occurances of a string in another string", ->
eq 1/0, count('abc', '')
@@ -46,7 +46,7 @@ test "the `count` helper counts the number of occurances of a string in another
eq 2, count('abcdabcd','abc')
#### `merge`
# `merge`
test "the `merge` helper makes a new object with all properties of the objects given as its arguments", ->
ary = [0, 1, 2, 3, 4]
@@ -58,7 +58,7 @@ test "the `merge` helper makes a new object with all properties of the objects g
eq val, merged[key]
#### `extend`
# `extend`
test "the `extend` helper performs a shallow copy", ->
ary = [0, 1, 2, 3]
@@ -69,7 +69,7 @@ test "the `extend` helper performs a shallow copy", ->
eq 2, obj[2]
#### `flatten`
# `flatten`
test "the `flatten` helper flattens an array", ->
success = yes
@@ -77,7 +77,7 @@ test "the `flatten` helper flattens an array", ->
ok success
#### `del`
# `del`
test "the `del` helper deletes a property from an object and returns the deleted value", ->
obj = [0, 1, 2]
@@ -85,7 +85,7 @@ test "the `del` helper deletes a property from an object and returns the deleted
ok 1 not of obj
#### `last`
# `last`
test "the `last` helper returns the last item of an array-like object", ->
ary = [0, 1, 2, 3, 4]

View File

@@ -4,7 +4,7 @@
# * String Interpolation
# * Regular Expression Interpolation
#### String Interpolation
# String Interpolation
# TODO: refactor string interpolation tests
@@ -109,7 +109,7 @@ eq 'multiline nested "interpolations" work', """multiline #{
} work"""
#### Regular Expression Interpolation
# Regular Expression Interpolation
# TODO: improve heregex interpolation tests

View File

@@ -9,7 +9,7 @@
# * Non-Integer Literals
#### Decimal Integer Literals
# Decimal Integer Literals
test "call methods directly on numbers", ->
eq 4, 4.valueOf()
@@ -23,7 +23,7 @@ eq Number::toString, 42['toString']
eq Number::toString, 42.toString
#### Non-Integer Literals
# Non-Integer Literals
# Decimal number literals.
value = .25 + .75
@@ -37,3 +37,8 @@ eq Number::toString, .42['toString']
eq Number::toString, 4.2.toString
eq Number::toString, .42.toString
test '#1168: leading floating point suppresses newline', ->
eq 1, do ->
1
.5 + 0.5

View File

@@ -183,6 +183,22 @@ test "invoking functions with implicit object literals", ->
ok result.length is 3
ok result[2].c is 1
result = getA b: 13, a: 42, 2
eq 42, result
result = getArgs a:1, (1 + 1)
ok result[1] is 2
result = getArgs a:1, b
ok result.length is 2
ok result[1] is 30
result = getArgs a:1, b, b:1, a
ok result.length is 4
ok result[2].b is 1
throws -> CoffeeScript.compile "a = b:1, c"
test "some weird indentation in YAML-style object literals", ->
two = (a, b) -> b
obj = then two 1,
@@ -193,3 +209,9 @@ test "some weird indentation in YAML-style object literals", ->
d: e
f: 1
eq 1, obj[1]
test "#1274: `{} = a()` compiles to `false` instead of `a()`", ->
a = false
fn = -> a = true
{} = fn()
ok a

View File

@@ -59,7 +59,7 @@ test "use `::` operator on keywords `this` and `@`", ->
eq nonce, obj.withThis()
#### Existential Operator (Binary)
# Existential Operator (Binary)
test "binary existential operator", ->
nonce = {}
@@ -91,7 +91,7 @@ test "binary existential operator with negative number", ->
eq -1, a
#### Existential Operator (Unary)
# Existential Operator (Unary)
test "postfix existential operator", ->
ok (if nonexistent? then false else true)
@@ -114,7 +114,7 @@ test "postfix existential operator on expressions", ->
eq true, (1 or 0)?, true
#### `is`,`isnt`,`==`,`!=`
# `is`,`isnt`,`==`,`!=`
test "`==` and `is` should be interchangeable", ->
a = b = 1
@@ -130,7 +130,7 @@ test "`!=` and `isnt` should be interchangeable", ->
ok a isnt b
#### [not] in/of
# [not] in/of
# - `in` should check if an array contains a value using `indexOf`
# - `of` should check if a property is defined on an object using `in`
@@ -184,8 +184,12 @@ test "#768: `in` should preserve evaluation order", ->
ok a() not in [b(),c()]
eq 3, share
test "#1099: empty array after `in` should compile to `false`", ->
eq 1, [5 in []].length
eq false, do -> return 0 in []
#### Chained Comparison
# Chained Comparison
test "chainable operators", ->
ok 100 > 10 > 1 > 0 > -1

View File

@@ -20,6 +20,10 @@ test "division is not confused for a regular expression", ->
g = 1
eq 2, a / b/g
a = 10
b = a /= 4 / 2
eq a, 5
obj = method: -> 2
two = 2
eq 2, (obj.method()/two + obj.method()/two)
@@ -35,7 +39,7 @@ test "#584: slashes are allowed unescaped in character classes", ->
ok /^a\/[/]b$/.test 'a//b'
#### Heregexe(n|s)
# Heregexe(n|s)
test "a heregex will ignore whitespace and comments", ->
eq /^I'm\x20+[a]\s+Heregex?\/\/\//gim + '', ///

View File

@@ -7,7 +7,7 @@
# shared array
shared = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#### Slicing
# Slicing
test "basic slicing", ->
arrayEq [7, 8, 9] , shared[7..9]
@@ -53,7 +53,7 @@ test "string slicing", ->
ok str[-5..] is "vwxyz"
#### Splicing
# Splicing
test "basic splicing", ->
ary = [0..9]

View File

@@ -6,7 +6,7 @@
# * Soaked Function Invocation
#### Soaked Property Access
# Soaked Property Access
test "soaked property access", ->
nonce = {}
@@ -73,7 +73,7 @@ test "operations on soaked properties", ->
eq yes, delete a?.b.c
#### Soaked Method Invocation
# Soaked Method Invocation
test "soaked method invocation", ->
nonce = {}
@@ -96,7 +96,7 @@ test "#733", ->
eq a.b?.c?([2, 3]...), 2
#### Soaked Function Invocation
# Soaked Function Invocation
test "soaked function invocation", ->
nonce = {}

View File

@@ -27,10 +27,9 @@
start = new Date
success = total = done = failed = 0
say = (msg, yay) ->
say = (msg) ->
div = document.createElement 'div'
div.appendChild document.createTextNode msg
div.style.color = if yay then 'green' else 'red'
stdout.appendChild div
msg
@@ -72,16 +71,9 @@
return
ok no
CoffeeScript.run = (code, cb) ->
try Function(CoffeeScript.compile code, wrap: no)()
catch e then cb(); throw e
cb yes
run = (name) ->
CoffeeScript.load "#{name}.coffee", (yay) ->
say "#{ if yay then '\u2714' else '\u3000' } #{name}", yay
++failed unless yay
CoffeeScript.load "#{name}.coffee", ->
say '\u2714 ' + name
fin() if ++done is names.length
fin = ->
@@ -92,12 +84,10 @@
say msg, yay
run name for name in names = [
'array_literals'
'arrays'
'assignment'
'boolean_literals'
'cake'
'booleans'
'classes'
'command'
'comments'
'compilation'
'comprehensions'
@@ -105,22 +95,22 @@
'exception_handling'
'formatting'
'function_invocation'
'function_literals'
'functions'
'helpers'
'importing'
'interpolation'
'javascript_literals'
'number_literals'
'object_literals'
'numbers'
'objects'
'operators'
'option_parser'
'range_literals'
'regular_expression_literals'
'ranges'
'regexps'
'repl'
'scope'
'slicing_and_splicing'
'soaks'
'string_literals'
'strings'
]
</script>