Compare commits

..

472 Commits
1.0.1 ... 1.1.3

Author SHA1 Message Date
Jeremy Ashkenas
3e41659095 CoffeeScript 1.1.3 2011-11-08 18:01:45 -05:00
Jeremy Ashkenas
d592d2c9cb Fixes #1803 -- use fs.watch instead of fs.watchFile ... more of a PITA, but hey. 2011-11-08 16:13:45 -05:00
Jeremy Ashkenas
78491b3a58 fixing relative path to jsl.conf 2011-11-08 16:04:10 -05:00
Jeremy Ashkenas
426f51db21 removing another process.binding() private snafu 2011-11-08 15:58:48 -05:00
Michael Ficarra
5ae4e06770 cake test: change eq to use egal semantics, paralleling arrayEq 2011-11-05 11:14:09 -04:00
Michael Ficarra
683b3afbc1 cake test: count number of complete tests that pass, not assertions 2011-11-05 11:12:50 -04:00
Michael Ficarra
1c86aee7a4 joyent/node#1914: REPL no longer hides undefined results 2011-11-05 10:35:27 -04:00
Michael Ficarra
11f048c368 compiling @jashkenas' last commit: f0043468a0 2011-11-05 10:34:44 -04:00
Jeremy Ashkenas
f0043468a0 removing process.ARGV from command.coffee, as it is gone in 0.6.0 2011-11-05 07:46:58 -04:00
Jeremy Ashkenas
a6081caf50 Merge pull request #1807 from TrevorBurnham/console_io
fixes #1798: using process.stderr in command.coffee
2011-10-27 08:42:17 -07:00
Trevor Burnham
c77f7737a5 Using process.stderr in command.coffee (fixes #1798) 2011-10-27 11:23:03 -04:00
Jeremy Ashkenas
91cb433b66 Revert "Merge branch 'console_io' of git://github.com/TrevorBurnham/coffee-script"
This reverts commit 2cb42b502c, reversing
changes made to 64bd4b3f74.
2011-10-24 16:19:15 -04:00
Jeremy Ashkenas
2cb42b502c Merge branch 'console_io' of git://github.com/TrevorBurnham/coffee-script 2011-10-24 14:56:20 -04:00
Jeremy Ashkenas
64bd4b3f74 rebuilding lexer.js 2011-10-24 14:51:41 -04:00
Trevor Burnham
41f2d2f789 Using console.log and console.error in command.coffee (fixes #1798) 2011-10-24 14:39:55 -04:00
Jeremy Ashkenas
913171f708 Merge pull request #1787 from revence27/binary
Binary notation integers (0b100 as 4).
2011-10-24 07:07:36 -07:00
Trevor Burnham
3f4daaf2ad Whoops, mergefail; corrected 2011-10-23 22:45:32 -04:00
Trevor Burnham
cf32ba0149 Merge pull request #1661 from TrevorBurnham/master
Allow user-added globals on the REPL (fixes #1654)
2011-10-23 19:34:07 -07:00
Trevor Burnham
6bec372684 Merging current master 2011-10-23 22:23:29 -04:00
Revence Kalibwani
620d8ce9ed Cleaner style. 2011-10-22 10:40:26 +03:00
Revence Kalibwani
bf8062ce7f Unindent. :-o 2011-10-21 22:49:47 +03:00
Revence Kalibwani
350e50600d Neater numberToken function. 2011-10-21 22:33:03 +03:00
Revence Kalibwani
938abae4b5 One test; viz., for binary literal. 2011-10-21 22:27:08 +03:00
Revence Kalibwani
264f881a81 Binary notation integers (0b100 as 4). 2011-10-21 21:44:56 +03:00
Michael Ficarra
d359764fba fixes #1774: generate safety wrapper only when necessary. awesome. 2011-10-17 16:12:09 -04:00
Jeremy Ashkenas
4a937ec3b8 Merge pull request #1757 from disnet/nocolor
Add flag to surpress color in cake output
2011-10-10 08:45:27 -07:00
Tim Disney
0ded5b3ff3 removing old changes 2011-10-06 21:39:24 -07:00
Tim Disney
c20a8ff53d using NODE_DISABLE_COLORS instead of flag 2011-10-06 18:43:53 -07:00
Tim Disney
2f38ed5e69 adding flag to surpress color in cake output 2011-10-06 16:17:36 -07:00
Michael Ficarra
054fe34434 fixes #1754: support filenames starting with - by using -- arg 2011-10-06 14:51:27 -04:00
Michael Ficarra
e686e3f6e9 fixes #1752: passing POSIX-style arguments to scripts through the CLI 2011-10-06 04:11:41 -04:00
Michael Ficarra
cf996d2c4a quick fix to part of new issue in #1099:
`not in []` unconditionally compiled to `false`
2011-10-03 06:43:00 -04:00
Michael Ficarra
9fef66ffcf empty regular expressions with flags still need to be compiled to /(?:)/ 2011-10-03 03:49:59 -04:00
Michael Ficarra
1627922060 unless is useful outside of single-line statements 2011-10-02 21:03:36 -03:00
Jeremy Ashkenas
981db17b8f Adopting coco-style efficient bound functions for the common case ... but not for class/prototypes. 2011-09-25 21:44:23 -04:00
Michael Ficarra
52dd348289 fixes #1724 for heregexen
TODO: DRY up that regex handling code so we don't have a duplicate test/error
2011-09-22 04:39:13 -04:00
Michael Ficarra
f4c1b20ec2 fixes #1724: regular expressions beginning with *
also normalised capitalisation in a few error messages
2011-09-22 04:09:58 -04:00
Michael Ficarra
08762a101c fixes #1723: operator precedence in unbounded splice compilation 2011-09-22 02:14:07 -04:00
Michael Ficarra
3b5c889040 fixes #1722: operator precedence in unbounded slice compilation 2011-09-21 18:56:20 -04:00
Jeremy Ashkenas
0171204e50 Merge pull request #1719 from jeremybanks/master
Upgrade jQuery in documentation from v1.4.2 to v1.6.4
2011-09-20 21:42:36 -07:00
Jeremy Banks
dd82b15b78 Upgrade jQuery in documentation from 1.4.2 to 1.6.4. 2011-09-21 00:27:32 -04:00
Jeremy Ashkenas
3d91b10927 Fixes #1714 2011-09-20 23:21:46 -05:00
Jeremy Ashkenas
65b3bf0d4c merging in the try coffeescript linking patch from Jeremy Banks, and regen-ing source. The newline patch makes a *huge* difference on the documentation page. 2011-09-20 22:42:19 -05:00
Jeremy Ashkenas
4c0b2372c7 Merge branch 'master' of https://github.com/jeremybanks/coffee-script 2011-09-20 22:33:35 -05:00
Jeremy Ashkenas
54110c98d9 Issue #1714 ... broken 'in' after raw range 'for' 2011-09-20 22:28:07 -05:00
Michael Ficarra
a2c593bc2c too many newlines after errors in the REPL 2011-09-19 02:18:42 -04:00
Jeremy Banks
de0122dc17 Moving [Link] button's inline style to stylesheet. 2011-09-18 21:53:08 -04:00
Jeremy Banks
2c43a9d209 Pulled Try CoffeeScript fragment prefix into a variable, other minor improvements. 2011-09-18 21:43:10 -04:00
Jeremy Ashkenas
6da70168a6 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-09-18 20:16:14 -05:00
Jeremy Ashkenas
0199515cef experimental change -- comments wanted. writing out helper functions and assignments as a single line, to minimize clutter. 2011-09-18 17:29:01 -05:00
Jeremy Ashkenas
37705e712b removing the extra newline that block comments take 2011-09-18 17:19:09 -05:00
Jeremy Ashkenas
d2b0404188 big whitespace / readability change. join top level block with extra newlines, and class definitions as well. 2011-09-18 17:16:39 -05:00
Jeremy Banks
80f9a20bfd Adds [Link] button to Try CoffeeScript interface. 2011-09-18 17:56:09 -04:00
Michael Ficarra
94a9551ffa fixes #1699 2011-09-18 00:52:30 -03:00
Jeremy Ashkenas
4419f7ca0f Issue #1703, - --x 2011-09-17 22:21:47 -04:00
Jeremy Ashkenas
19f77cfff5 Unified error handling in the lexer. 2011-09-17 21:39:24 -04:00
satyr
3cdee749c6 rewriter: followed up d03d288 2011-09-17 09:18:14 +09:00
satyr
d03d288a98 fixed #1299: overhauled token pairings 2011-09-17 08:26:04 +09:00
Jeremy Ashkenas
c5dbb1c933 Issue #1687. Keeping a reference to __originalDirname in Cake tasks, after Node's __dirname 2011-09-11 23:41:50 -04:00
Jeremy Ashkenas
85342f1e31 Issue #1682, futher refinements to command-line help. 2011-09-11 22:43:28 -04:00
Jeremy Ashkenas
c1f9ae8208 style tweaks for #1687 2011-09-11 22:25:27 -04:00
Jeremy Ashkenas
bd1672621c Merge pull request #1687 from fortes/1686_cakefile_parent_dirs
Check parent directories for Cakefiles
2011-09-11 19:17:20 -07:00
Michael Ficarra
2d6cda7f32 sorting options in coffee --help 2011-09-11 22:04:44 -04:00
Jeremy Ashkenas
2c8690ee39 Merge pull request #1691 from willbailey/master
I didn't see an example of how to do this and thought it might be helpful for others.
2011-09-11 18:11:14 -07:00
Filipe Fortes
6c98480a1e Remove extra call to path.exists when finding Cakefile 2011-09-11 20:50:27 -04:00
Will Bailey
98cc7eb149 [docs] examples of using guards and indices in array comprehensions 2011-09-11 12:43:39 -07:00
Filipe Fortes
6278930aef Check parent directories for Cakefiles. Closes #1686 2011-09-10 20:46:25 -04:00
Jeremy Ashkenas
0b57b3136c Edited src/command.coffee via GitHub 2011-09-09 23:44:34 -03:00
Michael Ficarra
46b7a2d17c Merge branch '1643_splatted_access' of https://github.com/geraldalewis/coffee-script 2011-09-09 22:07:58 -04:00
Trevor Burnham
588af1f6af Merge pull request #1673 from codelahoma/watch-help
clarify --watch option in "coffee -h" output
2011-09-09 18:50:13 -07:00
Gerald Lewis
34f99c4a79 #1643: Bugfix in heredoc in test for 1643 2011-09-09 21:30:00 -04:00
Jeremy Ashkenas
a0d4242da4 Merge pull request #1666 from geraldalewis/1643_splatted_access
#1643 splatted access
2011-09-09 16:17:24 -07:00
Gerald Lewis
447c3639e7 #1643: compiled JS 2011-09-09 19:03:40 -04:00
Gerald Lewis
f0e276c63a #1643: Remove superfluous assignable check from destructured Splats 2011-09-09 19:03:12 -04:00
Gerald Lewis
7d4e693d20 #1643: Updated tests 2011-09-09 18:59:35 -04:00
Gerald Lewis
03372c9b29 #1643: Tag subpatterns in Assign#compilePatternMatch to prevent appending reference to RHS 2011-09-09 18:58:59 -04:00
Gerald Lewis
6d0ba4b3bd #1643: Clean up Assign#compile and Assign#compilePatternMatch 2011-09-09 18:57:57 -04:00
Gerald Lewis
6622f015ab #1643: Add unwrap method to Splat 2011-09-09 18:55:08 -04:00
Rod Knowlton
d6ec5e40cc tiny edit 2011-09-09 15:24:56 -05:00
Rod Knowlton
c44b80b6b6 build to update lib 2011-09-08 20:02:12 -05:00
Rod Knowlton
9db814f70d change phrasing of watch help text 2011-09-08 18:04:59 -05:00
Rod Knowlton
d7f9054108 change phrasing of watch help text 2011-09-08 18:02:23 -05:00
Rod Knowlton
2df9204104 change phrasing of watch help text 2011-09-08 17:59:39 -05:00
Rod Knowlton
ed4f7046d3 clarify --watch option in "coffee -h" output 2011-09-07 20:19:14 -05:00
satyr
ad1bc1e0b8 closes #1669; loop results are now collected in the same way as auto-returns are generated 2011-09-07 12:13:23 +09:00
satyr
2ea51b02cc fixed #1102; lexer: cleaned up unfinished 2011-09-07 02:56:14 +09:00
Jeremy Ashkenas
036fc561a2 Merge pull request #1662 from geraldalewis/1195_trailing_semicolons
#1195 Ignore trailing semicolons
2011-09-06 06:15:13 -07:00
Jeremy Ashkenas
a8185407fa Merge pull request #1663 from TrevorBurnham/node_version
Bump node dependency from 0.2.5 to 0.4.0
2011-09-05 12:48:49 -07:00
Trevor Burnham
1cc85aad64 Adding tests for CoffeeScript.eval 2011-09-04 13:57:09 -04:00
Trevor Burnham
067cd4b4fe Allowing eval with a sandbox, but defaulting to global context 2011-09-04 13:53:44 -04:00
Trevor Burnham
6d68b1f5ad Bumping node dependency from 0.2.5 to 0.4.0 2011-09-04 13:32:57 -04:00
Trevor Burnham
e8b3e2f248 Restoring the ability to CoffeeScript.eval code in a sandbox 2011-09-04 12:38:59 -04:00
Trevor Burnham
d5aad39b3f Bumping node dependency to 0.4.0 (see discussion at #1661) 2011-09-04 12:27:38 -04:00
Trevor Burnham
cce9ac28c9 Taking an axe to the sandbox (see discussion at #1661) 2011-09-04 12:26:39 -04:00
Gerald Lewis
49e3a91d67 tests for #1195: lex out semicolons before newlines and at end of program 2011-09-04 12:18:38 -04:00
Gerald Lewis
76b6a1771b fixes #1195: lex out semicolons before newlines and at end of program 2011-09-04 12:18:22 -04:00
Michael Ficarra
c88cb5c8b5 Another attempt to fix #1580... still haven't come up with a good way to
test it, though. Hopefully the third time is... the one that works.
2011-09-04 12:16:04 -04:00
Trevor Burnham
efd503f84a Reloading globals after every REPL command (actually fixes #1654) 2011-09-04 10:05:26 -04:00
Trevor Burnham
7ba52ae729 Blacklisting certain globals from REPL rather than whitelisting (fixes #1654) 2011-09-04 09:54:13 -04:00
Gerald Lewis
8ebda7ac02 tests for #1643: splatted accesses in destructuring assignments no longer create obj.key var declarations 2011-09-01 14:47:30 -04:00
Gerald Lewis
43a8b46203 fixes #1643: splatted accesses in destructuring assignments no longer create obj.key var declarations 2011-09-01 14:47:10 -04:00
Jeremy Ashkenas
d1af5163eb Merge pull request #1647 from dget/patch-1
Adding a link to the change log to the current version on the webpage
2011-08-31 15:23:39 -07:00
dget
ee6eccbfe1 Adding a link to the change log to the current version, to make it easier to see what's changed. 2011-08-31 16:10:06 -03:00
Jeremy Ashkenas
d37cfc69d9 Merge pull request #1641 from geraldalewis/1591_splats_in_destructuring
1591 Splatted Expressions in Destructuring Assignment Must Be Assignable
2011-08-30 08:23:26 -07:00
Gerald Lewis
3a6c8c92b3 tests for #1591: splatted expressions in destructuring assignment must be assignable 2011-08-30 11:12:39 -04:00
Gerald Lewis
e17b67e6f2 fixes #1591: splatted expressions in destructuring assignment must be assignable 2011-08-30 11:12:25 -04:00
Jeremy Ashkenas
c0e0ede09f Merge pull request #1636 from mineo/patch-1
alert(html) in the heredoc example
2011-08-29 20:35:23 -07:00
Wieland Hoffmann
a4425471fd alert(html) in the heredoc example 2011-08-30 10:42:34 +03:00
Michael Ficarra
b4e2240ede fixes #1633: error output when using coffee -e 2011-08-27 13:21:03 -04:00
Michael Ficarra
539b872e02 compiled src/coffee-script.coffee 2011-08-27 13:20:29 -04:00
Michael Ficarra
2ff6c4c3fc fixes #1630: in should check indices of the right operand when it can
pass a `hasOwnProperty` check for them
2011-08-26 15:44:00 -04:00
Jeremy Ashkenas
8686e31271 Merge pull request #1624 from johnyanarella/master
--join fails silently with no resulting output file
2011-08-22 10:39:47 -07:00
John Yanarella
0bf0f6d721 Resolved an issue that could occur while compiling with the --join option which would cause the compiler to silently fail with no resulting output file.
While recursively traversing a source directory, if a directory was encountered containing either no .coffee files (ex. an .svn metadata directory) or where the last file processed in that directory was not a .coffee file, compileJoin() might never be called.

This issue was originally introduced by a (well-needed) optimization in commit dc272a680b.

In join mode, anytime the 'unprocessed' count is decremented, the remaining file count should be evaluated to determine if it is time to run compileJoin().  Previously, compileJoin() would only ever be called in one of the four possible terminating branches of this recursive asynchronous operation.
2011-08-22 13:32:54 -04:00
Michael Ficarra
3ef0c1c88a reverting stylistic change from parent commit 2011-08-16 10:53:08 -03:00
Michael Ficarra
5b115ddb74 (probably) expressing Jeremy's intentions
edited via Github, so no changes to /lib/coffee-script.js
2011-08-16 08:53:15 -03:00
Jeremy Ashkenas
604e39b413 Merge pull request #1605 from geraldalewis/1513_obj_front_ops
#1513 Top level bare obj literals with unary and exist ops
2011-08-15 08:55:24 -07:00
Gerald Lewis
f3253f4f5c tests for #1513 2011-08-15 11:06:53 -04:00
Gerald Lewis
2fb2ddb9b4 fixes #1513 -- top level bare obj literals now wrapped in parens for unary and exists operations 2011-08-15 11:06:36 -04:00
Jeremy Ashkenas
7e4d6198d4 #1568, new super in a function body. 2011-08-14 17:24:19 -04:00
Jeremy Ashkenas
8c31f2ee44 Adding a test for #1595 2011-08-14 17:08:12 -04:00
Jeremy Ashkenas
9a026e51bd Issue #1595, reusing a variable in a catch leads to missing declaration. 2011-08-14 17:04:54 -04:00
Jeremy Ashkenas
50982b668b Issue #1598 -- enabling super() calls in static functions in class bodies. 2011-08-14 16:51:59 -04:00
Jeremy Ashkenas
c6c988ae28 Revert "Ensure test failures get fully outputted."
This reverts commit 41b8b3256d.
2011-08-14 16:39:38 -04:00
Jeremy Ashkenas
306d84828d Merge branch 'super' of https://github.com/aseemk/coffee-script 2011-08-14 16:39:12 -04:00
Jeremy Ashkenas
4710e744dc clarifying Cake on the homepage. 2011-08-14 16:24:26 -04:00
Aseem Kishore
0b3029dd3f Add test for static super calls.
Tests jashkenas/coffee-script#1598. Fails currently as expected.
2011-08-12 15:10:19 -07:00
Aseem Kishore
41b8b3256d Ensure test failures get fully outputted.
Node's console.log() is non-blocking, so I was seeing test failure output get
cut off since it was happening on process exit. No more!
2011-08-12 14:56:33 -07:00
Jeremy Ashkenas
42f2bd926b Merge pull request #1590 from geraldalewis/proto_access
#1234 Protoype Access in :: Operator
2011-08-12 11:21:46 -07:00
Gerald Lewis
197d07cc85 revised tests for #1234 thanks to @michaelficarra 2011-08-12 14:11:44 -04:00
Gerald Lewis
c9fd0659c2 revised patch for #1234; consolidated Value#push and Value#concat into Value#add; removed unnecessary INDEX_PROTO 2011-08-12 13:38:34 -04:00
Michael Ficarra
fa2fbf0c60 minor enhancements to tests for #1005 2011-08-11 02:17:48 -04:00
Michael Ficarra
c3fe29455b finishing up fix for #1009: class @do; it's a little bit ugly, but it
makes sense to do it this way
2011-08-11 01:52:10 -04:00
Michael Ficarra
df5aca9348 fixes #1005: invalid identifiers allowed on LHS of destructuring
assignment
2011-08-11 01:11:33 -04:00
Gerald Lewis
ab0b36a53f test for #1234 2011-08-10 22:01:47 -04:00
Gerald Lewis
29a44b84d5 fixes #1234 ... :: now creates an intermediary "prototype" Access node before any additional property accesses 2011-08-10 22:01:47 -04:00
Michael Ficarra
e5b77b180a fixes #580 by deleteing the compiler from require.cache and requireing it again 2011-08-10 21:26:16 -04:00
Michael Ficarra
fc1cdfc913 Merge pull request #1584 from MichaelBlume/grammar_path
fix path to grammar file
2011-08-08 22:43:08 -07:00
Mike Blume
8c5027abb9 fix the output path too 2011-08-08 22:37:48 -07:00
Mike Blume
333daf33a3 fix path to grammar file 2011-08-08 22:34:09 -07:00
Michael Ficarra
064f2b5787 README: corrected compilation instruction; added execution instruction 2011-08-09 00:23:55 -03:00
Michael Ficarra
13ac72239a repl: allowing tab completion of an empty line and masking __X
reserved helpers from tab completion; fixes #1583
2011-08-08 18:26:50 -04:00
Michael Ficarra
818216374c Merge branch 'restructuring' of github.com:jashkenas/coffee-script 2011-08-08 13:21:58 -04:00
Michael Ficarra
5a9cf5722f conditional compilation update as per discussion in
a5ba0c27ae
2011-08-08 12:55:22 -04:00
Michael Ficarra
a5ba0c27ae breaking long lines created by 803a7d06e3 2011-08-08 12:27:53 -04:00
Jeremy Ashkenas
f6d3953bc6 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-08-08 10:04:31 -04:00
Jeremy Ashkenas
c9a5135e23 Merge branch 'gh-pages' 2011-08-08 10:04:09 -04:00
Jeremy Ashkenas
ab326aea4c removing errant line from changelog 2011-08-08 10:03:41 -04:00
Michael Ficarra
7cf5988099 allowing classes to extend expressions; fixes #1482 2011-08-07 05:02:01 -04:00
Michael Ficarra
35a30fbd6d cleaned up block comment output; fixes #1186 2011-08-07 03:51:51 -04:00
Michael Ficarra
6608a7aa98 fixes #1100: precedence in or-test compilation of in 2011-08-07 03:43:41 -04:00
Michael Ficarra
803a7d06e3 output formatting cleanup; fixes #1254: improve when compilation; also
causes single-line, single-statement conditional bodies to sit next to
their conditions
2011-08-07 02:59:37 -04:00
Michael Ficarra
be4685589a fixes #1009: classes with reserved words as determined names 2011-08-07 01:48:27 -04:00
Michael Ficarra
bf7d62affb avoiding require.paths poison pill from newer node releases in
`CoffeeScript.eval`
2011-08-06 18:12:55 -04:00
Michael Ficarra
718b73a0ba removed some unnecessary assignment; related: #1491 2011-08-06 13:31:14 -04:00
Michael Ficarra
c2a43f70f2 moved src/coffee-script/*.coffee to src as per discussion in #1246 2011-08-05 18:39:55 -04:00
Michael Ficarra
c222da9dd6 Merge branch 'restructure' of https://github.com/gfxmonk/coffee-script into restructuring
Conflicts:
	Cakefile
2011-08-05 17:47:54 -04:00
Jeremy Ashkenas
55e366f29c Merge pull request #1571 from MichaelBlume/fix-ternary
shorten one of the ternaries
2011-08-04 21:02:16 -07:00
Jeremy Ashkenas
4e71aad124 Merge pull request #1573 from geraldalewis/1464_bound_static_methods
1464 bound static methods
2011-08-04 21:00:46 -07:00
Jeremy Ashkenas
a03f2fe937 Jison goes to 11 2011-08-04 23:59:46 -04:00
Jeremy Ashkenas
5710992156 Merge pull request #1576 from sstephenson/dev-dependencies
Add uglify-js and jison as development dependencies
2011-08-04 20:58:40 -07:00
Jeremy Ashkenas
0ed9be4665 rebuilding the browser js with a new Jison-generated parser. 2011-08-04 23:57:40 -04:00
Sam Stephenson
d665c3a75f Add uglify-js and jison as development dependencies 2011-08-04 22:55:53 -05:00
Jeremy Ashkenas
48f3c70013 bumping version to 1.1.3-pre for Trevor's sake ;) 2011-08-04 23:52:27 -04:00
Jeremy Ashkenas
8a4ec8f562 Adding books + screencasts to the homepage 2011-08-04 23:45:38 -04:00
Jeremy Ashkenas
1a652a9736 CoffeeScript 1.1.2 2011-08-04 23:17:23 -04:00
Mike Blume
15fed8d17f fix another long ternary in the lib 2011-08-04 19:58:27 -07:00
Mike Blume
396f9b3a12 eliminate unnecessary assignment
there's no need to assign this entire if statement to condpart
when condpart is assigned at every endpoint
2011-08-04 19:58:27 -07:00
Michael Ficarra
1f69200d06 Merge pull request #1542 from MichaelBlume/master
Check for existence of this.context. Avoid build error.
2011-08-04 13:23:33 -07:00
Gerald Lewis
0e0d625adb test for #1464 ... bound class methods now keep context 2011-08-04 13:54:26 -04:00
Gerald Lewis
638dbbecbc fixes issue #1464 ... bound class methods now keep context 2011-08-04 13:54:26 -04:00
Michael Ficarra
9f89a83c27 formatting and rewording a test 2011-08-01 17:28:52 -04:00
Mike Blume
178af9de56 check existence of this.context. Avoid build error
https://github.com/jashkenas/coffee-script/issues/1541

with thanks to analyst74 whose bug report made the fix trivial =)
2011-07-31 18:45:30 +00:00
Michael Ficarra
e7854bec09 changed uses of the slice method to CS slices in nodes.coffee 2011-07-31 13:25:57 -04:00
satyr
9b9612e09c fixed #1322; block comments no longer get out of implicitly called implicit objects 2011-07-27 18:49:48 +09:00
Michael Ficarra
d2d02bf91d Cakefile: build:full exits unsuccessfully when tests or builds fail;
test failures now print full stack trace
2011-07-18 17:47:31 -04:00
Jeremy Ashkenas
860c5030d2 Merge pull request #1527 from breckinloggins/fix_1446
Fix for issue #1446: Compiler fails with unrelated exception on file permissions problems
2011-07-18 12:38:23 -07:00
Breckin Loggins
2d54fea90c Fix for issue #1446: Compiler crashes on permissions error instead of giving meaningful error message 2011-07-18 14:29:45 -05:00
Breckin Loggins
5ee0254ce5 Merge branch 'master' of git://github.com/jashkenas/coffee-script 2011-07-18 14:21:09 -05:00
Jeremy Ashkenas
37019dab1c Merge pull request #1522 from breckinloggins/fix_1470
Issue #1470: Command line compiler now assumes ".coffee" extension if left off of file names
2011-07-18 06:12:44 -07:00
Breckin Loggins
2b31f28f8f Replacing heredoc in test with simple string 2011-07-17 15:50:42 -05:00
Michael Ficarra
8931e31991 improving test for #1492 2011-07-17 16:43:50 -04:00
Jeremy Ashkenas
813efbe1d3 Merge pull request #1517 from breckinloggins/master
Patch for issue #1492 (consecutive semicolons in compiled output)
2011-07-17 13:31:32 -07:00
Jeremy Ashkenas
7790df0df6 Merge pull request #1518 from taku0/fix_pluckDirectCall
Removed a garbage code in `pluckDirectCall`.
2011-07-17 09:21:29 -07:00
Jeremy Ashkenas
c2b32df22b Merge pull request #1460 from yyyc514/fix_print_with_join
compileJoin should happen once after all files are read
2011-07-17 09:11:32 -07:00
Breckin Loggins
479a2e0383 Using string interpolation when adding extension 2011-07-16 14:44:26 -05:00
Breckin Loggins
471cf1d51a Issue #1470: Cleaning up logic on extension detection 2011-07-16 14:42:45 -05:00
taku0
ecdaad2fd6 Removed a garbage code in pluckDirectCall.
`args` are removed at 094b876a38.
2011-07-17 02:31:50 +09:00
Breckin Loggins
3e20622bd5 Test implementation of issue #1470. Assuming '.coffee' extension if file not found 2011-07-16 10:44:37 -05:00
Breckin Loggins
8a4a28bd33 Fixing issue #1492: Consecutive semicolons in compiled output in some situations 2011-07-16 09:34:46 -05:00
Jeremy Ashkenas
8fe59ed888 Fixing funkiness introduced in #1498. 2011-07-12 13:13:46 -04:00
Jeremy Ashkenas
1927213174 Merge pull request #1498 from breckinloggins/master
Some typo corrections and minor documentation edits
2011-07-12 09:07:48 -07:00
Michael Ficarra
cb8e147212 arranged and formatted nonContextGlobals list in REPL 2011-07-11 13:08:47 -04:00
Michael Ficarra
07baed89ed Added globals to the REPL that are (for a reason currently unknown to
me) not provided by `vm.Script.createContext`
2011-07-11 12:55:29 -04:00
Michael Ficarra
af1cf3400e fixes tab completion in the REPL 2011-07-10 14:26:31 -04:00
breckinloggins
eb53670676 Changing sentance structure in a grammar rule explanation 2011-07-09 18:33:19 -05:00
breckinloggins
709dc73c27 Removing 'the' from the CoffeeScript Compiler for Windows link 2011-07-09 11:52:02 -05:00
breckinloggins
14e09d2ca8 One more minor correction to main documentation 2011-07-09 10:03:04 -05:00
breckinloggins
0353b0ddd3 Small typo fixes in several files. Completed some missing documentation in nodes.coffee 2011-07-09 09:58:17 -05:00
breckinloggins
f2ba08f77f Minor edits to the main documentation. Added a reference to @alisey's CoffeeScript Compiler for Windows. 2011-07-08 22:22:28 -05:00
Michael Ficarra
1d7d8cb4d2 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-07-06 22:16:30 -04:00
Michael Ficarra
6e9cfd8a33 allow Ctrl-C to escape an unwanted continuation prompt 2011-07-06 22:15:35 -04:00
Michael Ficarra
2a9fd34a03 Made line continuations in the REPL much, much nicer and moved all of
the REPL-specific code out of CoffeeScript.eval and into the REPL
function (thanks for the suggestion, @TrevorBurnham)
2011-07-06 22:15:35 -04:00
Jeremy Ashkenas
b1111c96ca fixes issue #1490 ... jsl.conf is incorrectly npmignored. 2011-07-06 22:15:35 -04:00
Michael Ficarra
55383155e5 More accurately emulating node's REPL behaviour with regard to _
assignment. Also addresses `i for i in [1..3]` regression introduced by
fff4c9c672 and noticed by @satyr
2011-07-06 22:15:35 -04:00
Michael Ficarra
bb1502a9d7 output a newline before exiting REPL 2011-07-06 22:15:35 -04:00
Michael Ficarra
40ee30ecde Fixes #1035, #1425, and #1444: (another) overhaul of REPL and
CoffeeScript.eval. Instead of writing about all the changes and why I
made those decisions, I'll just answer any questions in the commit
comments, so add a commit comment if you want to question anything.
Thanks to @TrevorBurnham and @satyr for their help/contributions. Also,
closes #1487. And still no REPL tests...
2011-07-06 22:15:35 -04:00
Jeremy Ashkenas
4ff00359b6 fixes #1478, documentation. 2011-07-06 22:15:35 -04:00
Michael Ficarra
f433fa4187 improved test for #1436 2011-07-06 22:15:35 -04:00
Michael Ficarra
594ead00e8 improved tests for #1416, fixed accidental scope leak in test for #1420 2011-07-06 22:15:35 -04:00
Timothy Jones
5adf3b8865 Fixes #1461. Existential assignment now correctly reports if it is a statement. 2011-07-06 22:15:35 -04:00
Timothy Jones
4fc52cd08e Fixes #1467. Catch now introduces its parameter to scope. 2011-07-06 22:15:35 -04:00
Jann Horn
4af47f0c26 second part of fixing #1416 2011-07-06 22:15:35 -04:00
Jann Horn
9d3510a1e4 added another test for #1416 2011-07-06 22:15:35 -04:00
Jann Horn
18f6ad9583 fixes #1416: don't omit one 'new' when compiling 'new new' 2011-07-06 22:15:35 -04:00
Jann Horn
4c70ea5e09 test for #1416: don't omit one 'new' when compiling 'new new' 2011-07-06 22:15:35 -04:00
Jann Horn
d32c060e05 fixed #1436 2011-07-06 22:15:35 -04:00
Jann Horn
caa3d1ab5d added a test for #1436, for etc. should work as normal property names 2011-07-06 22:15:34 -04:00
Michael Ficarra
d3e809da38 subliminally promoting the use of interpolation in the documentation 2011-07-06 22:15:34 -04:00
Jeremy Ashkenas
5ab892d009 Merge pull request #1426 from jashkenas/documentationInterpolations
promote the use of interpolation in the documentation
2011-07-06 17:52:32 -07:00
Michael Ficarra
54dbc0fdf8 allow Ctrl-C to escape an unwanted continuation prompt 2011-07-06 17:00:13 -04:00
Michael Ficarra
003f91d43d Made line continuations in the REPL much, much nicer and moved all of
the REPL-specific code out of CoffeeScript.eval and into the REPL
function (thanks for the suggestion, @TrevorBurnham)
2011-07-06 16:36:07 -04:00
Jeremy Ashkenas
83806a4d77 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-07-06 16:06:47 -04:00
Jeremy Ashkenas
c4324f1db2 fixes issue #1490 ... jsl.conf is incorrectly npmignored. 2011-07-06 16:06:17 -04:00
Michael Ficarra
b9c3e0e640 More accurately emulating node's REPL behaviour with regard to _
assignment. Also addresses `i for i in [1..3]` regression introduced by
fff4c9c672 and noticed by @satyr
2011-07-06 13:06:18 -04:00
Michael Ficarra
60e51a238d output a newline before exiting REPL 2011-07-06 13:05:07 -04:00
Michael Ficarra
fff4c9c672 Fixes #1035, #1425, and #1444: (another) overhaul of REPL and
CoffeeScript.eval. Instead of writing about all the changes and why I
made those decisions, I'll just answer any questions in the commit
comments, so add a commit comment if you want to question anything.
Thanks to @TrevorBurnham and @satyr for their help/contributions. Also,
closes #1487. And still no REPL tests...
2011-07-06 03:54:36 -04:00
gfxmonk
ab17f41652 Moved src/*.coffee under src/coffee-script/ so that lib can be added to $NODE_PATH and only expose the top-level coffee-script namespace. Fixes #1246 2011-07-05 21:58:04 +10:00
Jeremy Ashkenas
18ab569b2d Merge branch 'master' of github.com:jashkenas/coffee-script 2011-07-01 08:30:38 -04:00
Jeremy Ashkenas
2951d34dc0 fixes #1478, documentation. 2011-07-01 08:30:12 -04:00
Michael Ficarra
0cc5379caa improved test for #1436 2011-06-30 12:15:00 -04:00
Michael Ficarra
f6fcfa831c Merge branch 'bugfix-1436' of git://github.com/thejh/coffee-script into thejh_1448 2011-06-30 11:53:24 -04:00
Michael Ficarra
c93fc3ec76 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-06-30 11:46:32 -04:00
Michael Ficarra
7b5f012f79 improved tests for #1416, fixed accidental scope leak in test for #1420 2011-06-30 11:35:29 -04:00
Timothy Jones
22cee5d2d6 Fixes #1461. Existential assignment now correctly reports if it is a statement. 2011-06-29 18:54:23 -04:00
Timothy Jones
0f18dff464 Fixes #1467. Catch now introduces its parameter to scope. 2011-06-29 18:54:23 -04:00
Timothy Jones
e38aeefb5c Fixes #1461. Existential assignment now correctly reports if it is a statement. 2011-06-26 03:08:38 +12:00
Timothy Jones
baa983ac33 Fixes #1467. Catch now introduces its parameter to scope. 2011-06-26 02:34:52 +12:00
Josh Goebel
cd65c66cf9 combine conditions 2011-06-23 06:54:06 -04:00
Josh Goebel
dc272a680b compileJoin should happen once after all files are read 2011-06-23 04:42:12 -04:00
ngn
6f64fc266d added one more test for #1150 2011-06-22 19:42:07 +03:00
Jann Horn
73af3b17b1 second part of fixing #1416 2011-06-21 16:42:53 +02:00
Jann Horn
8b2884e40f added another test for #1416 2011-06-21 16:42:20 +02:00
Jann Horn
f0c22f390d fixes #1416: don't omit one 'new' when compiling 'new new' 2011-06-20 18:38:29 +02:00
Jann Horn
11f2cd4515 test for #1416: don't omit one 'new' when compiling 'new new' 2011-06-20 18:38:07 +02:00
ngn
5ce7984a2b Another attempt to fix #1150
Here's how the algorithm in balancedString() was modified.  When we
encounter a slash in an interpolation, we:

    * try to find a heregex right after it; if found---skip it.  Three
      slashes always terminate a heregex, no matter if there is an open
      "#{" before them or not, so we don't have to bother about
      sub-interpolations inside the heregex.

    * try to find a regex right after it; if found---skip it.  Simple
      regexen can't contain interpolations.

    * otherwise, assume that the slash means division and carry on.
2011-06-19 20:05:38 +03:00
Jann Horn
9699059226 fixed #1436 2011-06-19 10:49:41 +02:00
Jann Horn
9941c3f045 added a test for #1436, for etc. should work as normal property names 2011-06-19 10:49:19 +02:00
Michael Ficarra
25e7eeac8f Revert "Merge https://github.com/ngn/coffee-script"
This reverts commit 277e82bd03, reversing
changes made to 0f523de212.
2011-06-17 11:53:48 -04:00
Michael Ficarra
277e82bd03 Merge https://github.com/ngn/coffee-script 2011-06-17 11:32:08 -04:00
Michael Ficarra
a1f1afe3ed fixes #1442: javascript literals should increase line count when they
contain newlines
2011-06-17 11:26:39 -04:00
ngn
0f523de212 Fix for #1150: String interpolation regression 2011-06-15 20:34:12 +03:00
Michael Ficarra
47f12c453a subliminally promoting the use of interpolation in the documentation 2011-06-08 19:38:12 -04:00
Michael Ficarra
dfcff3f0fc adding regression test for #1420; also cleaned up a little trailing
whitespace in the function invocation tests
2011-06-07 04:10:40 -04:00
Michael Ficarra
522f2ee3b3 fixes #1420: (fn() ->) by causing the Lexer::tagParameters method to
give up looking for a parameter list when it saw a `CALL_START` token.
2011-06-07 03:58:36 -04:00
Michael Ficarra
8ce1fdb5bb enhancement for fix to #1409: when compiling as an array, ranges can't
have been given steps (would be a SyntaxError) ... yet
2011-06-02 09:28:13 -04:00
Michael Ficarra
a0efdac8ce removed trailing whitespace in source files 2011-06-02 02:00:47 -04:00
Michael Ficarra
22bc54f974 fixes #1409: creating large ranges outside of a function body 2011-06-02 01:50:31 -04:00
Michael Ficarra
e240621a72 test for #1409 2011-06-02 01:49:28 -04:00
Michael Ficarra
35c2a72ad2 REPL blank line fix 2011-06-02 01:34:55 -04:00
Michael Ficarra
10ec1a659f fixes #1398: comments in the REPL 2011-05-28 22:39:27 -04:00
Jeremy Ashkenas
1fb34e42a6 Revert "fixed condext during construction of bound functions; now using native"
This reverts commit 8d6e33c2cf.
2011-05-28 18:58:48 -04:00
Jeremy Ashkenas
7082000e66 Revert "switched to canonical two-space indentation in __bind helper"
This reverts commit 6a40807330.
2011-05-28 18:58:38 -04:00
Jeremy Ashkenas
79fff367c2 Revert "__bind helper: caching ctor"
This reverts commit 9cbf2a82ec.
2011-05-28 18:58:28 -04:00
Michael Ficarra
9cbf2a82ec __bind helper: caching ctor 2011-05-27 18:41:31 -04:00
Michael Ficarra
6a40807330 switched to canonical two-space indentation in __bind helper 2011-05-27 18:18:22 -04:00
Michael Ficarra
8d6e33c2cf fixed condext during construction of bound functions; now using native
Function::bind when it is available. related: #1363
2011-05-27 18:03:57 -04:00
Michael Ficarra
085874d5f3 hopefully the last enhancement for my #1380 fix 2011-05-25 12:57:45 -04:00
Michael Ficarra
94fb7e32ea removing accidentally-committed console.log 2011-05-25 04:22:03 -04:00
Michael Ficarra
042f7ec791 enhancement for #1380 fix 2011-05-25 04:10:50 -04:00
Michael Ficarra
e4f47a05f6 merging @TrevorBurnham's pull request #1314, enhancing CS.eval; closes #1314 2011-05-25 03:53:51 -04:00
Michael Ficarra
bbf37e5229 Merge pull request #1388 from johnyanarella/master
'coffee' silently fails with no output when the --join option is specified and the source files specified include directories
2011-05-25 00:47:05 -07:00
Michael Ficarra
454aa8433b fixes #1390: persistence of non-enumerable global properties in the REPL 2011-05-25 03:43:10 -04:00
Michael Ficarra
bbf1c6a8df fixes #1380: super with reserved names 2011-05-25 03:22:26 -04:00
Michael Ficarra
8e5eff5e1e test for #1380 2011-05-25 03:22:06 -04:00
Michael Ficarra
e64fa71185 fixes #1372: bound class methods with reserved names 2011-05-24 16:49:45 -04:00
Michael Ficarra
c8845643e5 fixes #1385: property access on parenthesized number literals 2011-05-24 16:27:07 -04:00
John Yanarella
371ff5e726 Fixed silently failing command line --join functionality when directories are specified for compilation. 2011-05-24 15:01:35 -04:00
Michael Ficarra
19520d8d35 merging in @fjakobs's heregex line number fix; closes #1374 2011-05-19 13:59:58 -04:00
Fabian Jakobs
abb11a7c0e fix line numbers after heregexps 2011-05-16 19:56:29 +02:00
Michael Ficarra
2ac74356bd cleaned up and optimized fix for #1354 (d91ccd4003) 2011-05-15 21:46:35 -04:00
Jeremy Ashkenas
004f13f0fc Merge pull request #1346 from adam-f/fixedsplatscope
Fixed improper scoping of siblings to the splat argument.
2011-05-15 17:13:50 -07:00
Adam Freidin
395a97ef07 removing unimportant changes for easy pull. 2011-05-15 17:11:02 -07:00
Jeremy Ashkenas
01b0cfc8ab Merge pull request #1324 from TrevorBurnham/node-modules
Use `require.main` instead of loop to get main module
2011-05-15 17:04:40 -07:00
Jeremy Ashkenas
f3758e4af0 Fixes #1328 2011-05-15 19:59:52 -04:00
Jeremy Ashkenas
2563324ed8 merging #1353 2011-05-15 18:56:11 -04:00
Jeremy Ashkenas
d91ccd4003 Issue #1354, 'in' with splatted arrays. 2011-05-15 18:50:04 -04:00
Jeremy Ashkenas
15ddb8e2ea simplifying some string interpolation in Range#compileNode 2011-05-15 17:07:59 -04:00
Jeremy Ashkenas
c056c93e19 Issue #1356 ... range comprehension optimization when a step is present. 2011-05-15 17:05:05 -04:00
Jeremy Ashkenas
9e32a5bfa1 fixing implicit invocations against inline try/catch. 2011-05-15 15:04:29 -04:00
Jeremy Ashkenas
cd5c41f351 Issue #1364, implicit calls against control structures. 2011-05-15 10:41:41 -04:00
Jeremy Ashkenas
b780d707ab fixing over whitespace-ing from the previous commit. 2011-05-15 10:16:46 -04:00
Jeremy Ashkenas
84ae563368 Merge branch 'master' of github.com:jashkenas/coffee-script 2011-05-15 10:08:55 -04:00
Jeremy Ashkenas
dddc7c6edb Issue #1368, block comment formatting. 2011-05-15 10:08:31 -04:00
Gerald Lewis
bd8d82809b Updated tests for #1216 and pull #1348 2011-05-11 09:11:41 -04:00
Gerald Lewis
51b7142805 Fix for #1216 and pull #1348; preserves original semantics while prettying the compiled output 2011-05-11 09:10:58 -04:00
Michael Ficarra
6c9ef76b95 fixed behavioural change accidentally introduced by #1348, thanks @satyr 2011-05-11 00:08:24 -04:00
Michael Ficarra
a024ec5b27 reverting tests from @geraldalewis's fix for #1216 2011-05-10 23:23:31 -04:00
Gerald Lewis
2212e959ac Fix for #1216 ?= compilation 2011-05-10 19:33:30 -04:00
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
Adam Freidin
dc499089e9 fixed name of simple destructuring test. 2011-05-08 15:00:27 -07:00
Michael Ficarra
f4b8e19c7f adding another failing test case related to #1182 2011-05-08 17:16:45 -04:00
Adam Freidin
1809c0e675 fixed 2nd scoping problem
x = 10
([x]) -> # used to not declare var x

this is one fix, the other way to fix
it is to remove the entire if ... olen is 1 ....
block... not sure if that's a good idea or not.
2011-05-08 04:59:44 -07:00
Adam Freidin
d11d69958f Removed extra index variable left from code thrash 2011-05-08 04:32:47 -07:00
Adam Freidin
6d2733405d Fixed splat sibling variable scope leak. 2011-05-07 20:46:08 -07:00
Adam Freidin
2dc2d162bc variadic arguments breaking out of scope (test) 2011-05-07 16:55:27 -07: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
Trevor Burnham
b9d3bc5b44 x = {} if x -> x and= {}, per Michael's suggestion
https://github.com/jashkenas/coffee-script/pull/1324/files#r25463
2011-05-03 17:06:34 -04:00
Trevor Burnham
fa2ed81485 Renaming root to mainModule in run method 2011-05-03 15:53:10 -04:00
Trevor Burnham
ea4a723379 Simpler method of getting the root module 2011-05-03 15:47:39 -04: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
131 changed files with 16089 additions and 10988 deletions

3
.gitignore vendored
View File

@@ -5,4 +5,5 @@ parser.output
test/fixtures/underscore
test/*.js
examples/beautiful_code/parse.coffee
*.gem
*.gem
/node_modules

View File

@@ -5,7 +5,7 @@
Cakefile
documentation/
examples/
extras/
extras/coffee-script.js
raw/
src/
test/

125
Cakefile
View File

@@ -1,14 +1,20 @@
fs = require 'fs'
path = require 'path'
{extend} = require './lib/helpers'
{extend} = require './lib/coffee-script/helpers'
CoffeeScript = require './lib/coffee-script'
{spawn, exec} = require 'child_process'
# ANSI Terminal Colors.
bold = '\033[0;1m'
red = '\033[0;31m'
green = '\033[0;32m'
reset = '\033[0m'
enableColors = no
unless process.platform is 'win32'
enableColors = not process.env.NODE_DISABLE_COLORS
bold = red = green = reset = ''
if enableColors
bold = '\033[0;1m'
red = '\033[0;31m'
green = '\033[0;32m'
reset = '\033[0m'
# Built file header.
header = """
@@ -22,16 +28,17 @@ header = """
"""
sources = [
'src/coffee-script.coffee', 'src/grammar.coffee'
'src/helpers.coffee', 'src/lexer.coffee', 'src/nodes.coffee'
'src/rewriter.coffee', 'src/scope.coffee'
]
'coffee-script', 'grammar', 'helpers'
'lexer', 'nodes', 'rewriter', 'scope'
].map (filename) -> "src/#{filename}.coffee"
# Run a CoffeeScript through our node/coffee interpreter.
run = (args) ->
run = (args, cb) ->
proc = spawn 'bin/coffee', args
proc.stderr.on 'data', (buffer) -> console.log buffer.toString()
proc.on 'exit', (status) -> process.exit(1) if status != 0
proc.on 'exit', (status) ->
process.exit(1) if status != 0
cb() if typeof cb is 'function'
# Log a message with a color.
log = (message, color, explanation) ->
@@ -53,30 +60,32 @@ task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options)
"ln -sfn #{lib}/bin/coffee #{bin}/coffee"
"ln -sfn #{lib}/bin/cake #{bin}/cake"
"mkdir -p ~/.node_libraries"
"ln -sfn #{lib}/lib #{node}"
"ln -sfn #{lib}/lib/coffee-script #{node}"
].join(' && '), (err, stdout, stderr) ->
if err then console.log stderr.trim() else log 'done', green
)
task 'build', 'build the CoffeeScript language from source', ->
task 'build', 'build the CoffeeScript language from source', build = (cb) ->
files = fs.readdirSync 'src'
files = ('src/' + file for file in files when file.match(/\.coffee$/))
run ['-c', '-o', 'lib'].concat(files)
run ['-c', '-o', 'lib/coffee-script'].concat(files), cb
task 'build:full', 'rebuild the source twice, and run the tests', ->
exec 'bin/cake build && bin/cake build && bin/cake test', (err, stdout, stderr) ->
console.log stdout.trim() if stdout
console.log stderr.trim() if stderr
throw err if err
build ->
build ->
csPath = './lib/coffee-script'
delete require.cache[require.resolve csPath]
unless runTests require csPath
process.exit 1
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
extend global, require('util')
require 'jison'
parser = require('./lib/grammar').parser
fs.writeFile 'lib/parser.js', parser.generate()
parser = require('./lib/coffee-script/grammar').parser
fs.writeFile 'lib/coffee-script/parser.js', parser.generate()
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
@@ -91,18 +100,19 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
code += """
require['./#{name}'] = new function() {
var exports = this;
#{fs.readFileSync "lib/#{name}.js"}
#{fs.readFileSync "lib/coffee-script/#{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'
@@ -123,7 +133,7 @@ task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', ->
throw err if err
task 'bench', 'quick benchmark of compilation time', ->
{Rewriter} = require './lib/rewriter'
{Rewriter} = require './lib/coffee-script/rewriter'
co = sources.map((name) -> fs.readFileSync name).join '\n'
fmt = (ms) -> " #{bold}#{ " #{ms}".slice -4 }#{reset} ms"
total = 0
@@ -151,19 +161,9 @@ runTests = (CoffeeScript) ->
passedTests = 0
failures = []
# make "global" reference available to tests
global.global = global
# Mix in the assert module globally, to make it available for tests.
addGlobal = (name, func) ->
global[name] = ->
passedTests += 1
func arguments...
addGlobal name, func for name, func of require 'assert'
global[name] = func for name, func of require 'assert'
# Convenience aliases.
global.eq = global.strictEqual
global.CoffeeScript = CoffeeScript
# Our test helper function for delimiting different test cases.
@@ -171,26 +171,29 @@ runTests = (CoffeeScript) ->
try
fn.test = {description, currentFile}
fn.call(fn)
++passedTests
catch e
e.description = description if description?
e.source = fn.toString() if fn.toString?
failures.push file: currentFile, error: e
failures.push filename: currentFile, error: e
# A recursive functional equivalence helper; uses egal for testing equivalence.
# See http://wiki.ecmascript.org/doku.php?id=harmony:egal
arrayEqual = (a, b) ->
egal = (a, b) ->
if a is b
# 0 isnt -0
a isnt 0 or 1/a is 1/b
else if a instanceof Array and b instanceof Array
return no unless a.length is b.length
return no for el, idx in a when not arrayEqual el, b[idx]
yes
else
# NaN is NaN
a isnt a and b isnt b
global.arrayEq = (a, b, msg) -> ok arrayEqual(a,b), msg
# A recursive functional equivalence helper; uses egal for testing equivalence.
arrayEgal = (a, b) ->
if egal a, b then yes
else if a instanceof Array and b instanceof Array
return no unless a.length is b.length
return no for el, idx in a when not arrayEgal el, b[idx]
yes
global.eq = (a, b, msg) -> ok egal(a, b), msg
global.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg
# When all the tests have run, collect and print errors.
# If a stacktrace is available, output the compiled function source.
@@ -200,26 +203,28 @@ runTests = (CoffeeScript) ->
return log(message, green) unless failures.length
log "failed #{failures.length} and #{message}", red
for fail in failures
{error, file} = fail
jsFile = file.replace(/\.coffee$/,'.js')
{error, filename} = fail
jsFilename = filename.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
console.log ''
log " #{error.description}", red if error.description
log " #{jsFile}: line #{line or 'unknown'}, column #{col or 'unknown'}", red
log " #{error.stack}", red
log " #{jsFilename}: line #{line ? 'unknown'}, column #{col ? 'unknown'}", red
console.log " #{error.source}" if error.source
return
# Run every test in the `test` folder, recording failures.
fs.readdir 'test', (err, files) ->
files.forEach (file) ->
return unless file.match(/\.coffee$/i)
filename = path.join 'test', file
fs.readFile filename, (err, code) ->
currentFile = filename
try
CoffeeScript.run code.toString(), {filename}
catch e
failures.push file: currentFile, error: e
files = fs.readdirSync 'test'
for file in files when file.match /\.coffee$/i
currentFile = filename = path.join 'test', file
code = fs.readFileSync filename
try
CoffeeScript.run code.toString(), {filename}
catch error
failures.push {filename, error}
return !failures.length
task 'test', 'run the CoffeeScript language test suite', ->

10
README
View File

@@ -1,4 +1,4 @@
=
{
} } {
{ { } }
@@ -26,10 +26,14 @@
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.)
Execute a script:
coffee /path/to/script.coffee
Compile a script:
coffee /path/to/script.coffee
coffee -c /path/to/script.coffee
For documentation, usage, and examples, see:
http://coffeescript.org/

View File

@@ -4,4 +4,4 @@ var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/cake').run();
require(lib + '/coffee-script/cake').run();

View File

@@ -4,4 +4,4 @@ var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/command').run();
require(lib + '/coffee-script/command').run();

View File

@@ -8,4 +8,4 @@ if car.speed < limit then accelerate()
winner = yes if pick in [47, 92, 13]
print inspect "My name is " + @name
print inspect "My name is #{@name}"

View File

@@ -1,2 +1,10 @@
# Eat lunch.
eat food for food in ['toast', 'cheese', 'wine']
# Fine dining
courses = ['salad', 'entree', 'dessert']
menu course + 1, dish for dish, course in courses
# Health conscious meal
foods = ['broccoli', 'spinach', 'chocolate']
eat food for food in foods when food isnt 'chocolate'

View File

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

View File

@@ -2,7 +2,7 @@ class Animal
constructor: (@name) ->
move: (meters) ->
alert @name + " moved " + meters + "m."
alert @name + " moved #{meters}m."
class Snake extends Animal
move: ->

View File

@@ -2,6 +2,6 @@ alert(
try
nonexistent / undefined
catch error
"And the error is ... " + error
"And the error is ... #{error}"
)

View File

@@ -1,4 +1,4 @@
yearsOld = max: 10, ida: 9, tim: 11
ages = for child, age of yearsOld
child + " is " + age
"#{child} is #{age}"

View File

@@ -6,5 +6,5 @@ if this.studyingEconomics
# Nursery Rhyme
num = 6
lyrics = while num -= 1
num + " little monkeys, jumping on the bed.
"#{num} little monkeys, jumping on the bed.
One fell out and bumped his head."

View File

@@ -85,6 +85,10 @@ code, pre, tt, textarea {
font-weight: normal;
color: black;
}
.timestamp small {
font-size: 11px;
text-transform: uppercase;
}
div.code {
position: relative;
background: #fff;
@@ -260,6 +264,10 @@ div.code {
width: 40px;
text-transform: none;
}
.navigation .code a.minibutton.permalink {
top: 38px;
display: block;
}
.bookmark {
display: block;

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

@@ -21,23 +21,29 @@ as the first argument to the action.</p> </td> <td class
<span class="nx">missingTask</span> <span class="nx">name</span> <span class="nx">unless</span> <span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">action</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node's
asynchrony may cause tasks to execute in a different order than you'd expect.
If no tasks are passed, print the help screen.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-&gt;</span>
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="s1">&#39;Cakefile&#39;</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="p">(</span><span class="s2">&quot;Cakefile not found in #{process.cwd()}&quot;</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">exists</span>
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">2</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s1">&#39;Cakefile&#39;</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">filename</span><span class="o">:</span> <span class="s1">&#39;Cakefile&#39;</span>
<span class="nv">oparse = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">switches</span>
<span class="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">options = </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTasks = </span><span class="o">-&gt;</span>
If no tasks are passed, print the help screen. Keep a reference to the
original directory name, when running Cake tasks from subdirectories. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-&gt;</span>
<span class="nv">global.__originalDirname = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="s1">&#39;.&#39;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">chdir</span> <span class="nx">cakefileDirectory</span> <span class="nx">__originalDirname</span>
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">2</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s1">&#39;Cakefile&#39;</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">filename</span><span class="o">:</span> <span class="s1">&#39;Cakefile&#39;</span>
<span class="nv">oparse = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">switches</span>
<span class="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">options = </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTasks = </span><span class="o">-&gt;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s1">&#39;&#39;</span>
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
<span class="nv">spaces = </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">desc = </span><span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s2">&quot;# #{task.description}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;cake #{name}#{spaces} #{desc}&quot;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</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>Print an error and exit when attempting to all an undefined task.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">missingTask = </span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</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>Print an error and exit when attempting to call an undefined task.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">missingTask = </span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;No such task: \&quot;#{task}\&quot;&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>When <code>cake</code> is invoked, search in the current and all parent directories
to find the relevant Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">cakefileDirectory = </span><span class="p">(</span><span class="nx">dir</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">dir</span> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s1">&#39;Cakefile&#39;</span>
<span class="nv">parent = </span><span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s1">&#39;..&#39;</span>
<span class="k">return</span> <span class="nx">cakefileDirectory</span> <span class="nx">parent</span> <span class="nx">unless</span> <span class="nx">parent</span> <span class="o">is</span> <span class="nx">dir</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;Cakefile not found in #{process.cwd()}&quot;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -7,12 +7,13 @@ source CoffeeScript into JavaScript.</p>
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="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="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>
<span class="nv">vm = </span><span class="nx">require</span> <span class="s1">&#39;vm&#39;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>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.3&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>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>
@@ -26,16 +27,41 @@ 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">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
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="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>
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>
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;.&#39;</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;module&#39;</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">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">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span>
<span class="k">else</span>
<span class="nx">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">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
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="k">return</span> <span class="nx">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
<span class="nv">Script = </span><span class="nx">vm</span><span class="p">.</span><span class="nx">Script</span>
<span class="k">if</span> <span class="nx">Script</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span><span class="o">?</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span> <span class="k">instanceof</span> <span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">().</span><span class="nx">constructor</span>
<span class="nv">sandbox = </span><span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
<span class="k">else</span>
<span class="nv">sandbox = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">()</span>
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
<span class="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</span>
<span class="k">else</span>
<span class="nv">sandbox = </span><span class="nx">global</span>
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="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></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
<span class="nv">Module = </span><span class="nx">require</span> <span class="s1">&#39;module&#39;</span>
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s1">&#39;eval&#39;</span><span class="p">)</span>
<span class="nv">sandbox.require = _require = </span><span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
<span class="nv">_module.filename = </span><span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span>
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s1">&#39;paths&#39;</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
<span class="nv">_require.resolve = </span><span class="p">(</span><span class="nx">request</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
<span class="nv">o = </span><span class="p">{}</span>
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
<span class="nv">o.bare = </span><span class="kc">on</span> <span class="c1"># ensure return value</span>
<span class="nv">js = </span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">o</span>
<span class="k">if</span> <span class="nx">sandbox</span> <span class="o">is</span> <span class="nx">global</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">js</span>
<span class="k">else</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
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>
@@ -11,25 +11,27 @@ interactive REPL.</p> </td> <td class="code">
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;events&#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>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
<span class="nv">printLine = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span>
<span class="nv">printWarn = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">binding</span><span class="p">(</span><span class="s1">&#39;stdio&#39;</span><span class="p">).</span><span class="nx">writeError</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">&#39;\n&#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>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s1">&#39;&#39;&#39;</span>
<span class="nv">printWarn = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">&#39;\n&#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>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> Usage: coffee [options] path/to/script.coffee</span>
<span class="s1"> If called without options, `coffee` will run your script.</span>
<span class="s1"> &#39;&#39;&#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>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
<span class="p">[</span><span class="s1">&#39;-b&#39;</span><span class="p">,</span> <span class="s1">&#39;--bare&#39;</span><span class="p">,</span> <span class="s1">&#39;compile without a top-level function wrapper&#39;</span><span class="p">]</span>
<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;-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;-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>
<span class="p">[</span><span class="s1">&#39;-b&#39;</span><span class="p">,</span> <span class="s1">&#39;--bare&#39;</span><span class="p">,</span> <span class="s1">&#39;compile without the top-level function wrapper&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-t&#39;</span><span class="p">,</span> <span class="s1">&#39;--tokens&#39;</span><span class="p">,</span> <span class="s1">&#39;print the tokens that the lexer produces&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-n&#39;</span><span class="p">,</span> <span class="s1">&#39;--nodes&#39;</span><span class="p">,</span> <span class="s1">&#39;print the parse tree that Jison produces&#39;</span><span class="p">]</span>
<span class="p">[</span> <span class="s1">&#39;--nodejs [ARGS]&#39;</span><span class="p">,</span> <span class="s1">&#39;pass options through to the &quot;node&quot; binary&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-v&#39;</span><span class="p">,</span> <span class="s1">&#39;--version&#39;</span><span class="p">,</span> <span class="s1">&#39;display CoffeeScript version&#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;pass a string from the command line as input&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-h&#39;</span><span class="p">,</span> <span class="s1">&#39;--help&#39;</span><span class="p">,</span> <span class="s1">&#39;display this help message&#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;-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 source CoffeeScript before compiling&#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;-n&#39;</span><span class="p">,</span> <span class="s1">&#39;--nodes&#39;</span><span class="p">,</span> <span class="s1">&#39;print out the parse tree that the parser produces&#39;</span><span class="p">]</span>
<span class="p">[</span> <span class="s1">&#39;--nodejs [ARGS]&#39;</span><span class="p">,</span> <span class="s1">&#39;pass options directly to the &quot;node&quot; binary&#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 output directory for compiled JavaScript&#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 out the compiled JavaScript&#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>
<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;-t&#39;</span><span class="p">,</span> <span class="s1">&#39;--tokens&#39;</span><span class="p">,</span> <span class="s1">&#39;print out the tokens that the lexer/rewriter produce&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-v&#39;</span><span class="p">,</span> <span class="s1">&#39;--version&#39;</span><span class="p">,</span> <span class="s1">&#39;display the version number&#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 rerun commands&#39;</span><span class="p">]</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>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">opts = </span><span class="p">{}</span>
<span class="nv">sources = </span><span class="p">[]</span>
<span class="nv">contents = </span><span class="p">[]</span>
@@ -47,29 +49,55 @@ Many flags cause us to divert before compiling anything. Flags passed after
<span class="k">return</span> <span class="nx">require</span> <span class="s1">&#39;./repl&#39;</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
<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="nv">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>
<span class="nv">unprocessed = </span><span class="p">[]</span>
<span class="nv">remaining_files = </span><span class="o">-&gt;</span>
<span class="nv">total = </span><span class="mi">0</span>
<span class="nx">total</span> <span class="o">+=</span> <span class="nx">x</span> <span class="k">for</span> <span class="nx">x</span> <span class="k">in</span> <span class="nx">unprocessed</span>
<span class="nx">total</span>
<span class="nv">trackUnprocessedFiles = </span><span class="p">(</span><span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">fileCount</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">?=</span> <span class="mi">0</span>
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">+=</span> <span class="nx">fileCount</span>
<span class="nv">trackCompleteFiles = </span><span class="p">(</span><span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">fileCount</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">-=</span> <span class="nx">fileCount</span>
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</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="o">and</span> <span class="nx">remaining_files</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
<span class="nx">compileJoin</span><span class="p">()</span>
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="nx">trackUnprocessedFiles</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">),</span> <span class="mi">1</span>
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="nv">base = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span>
<span class="nv">compile = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">compile = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">)</span> <span class="o">-&gt;</span>
<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">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">exists</span> <span class="o">and</span> <span class="nx">source</span><span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">..]</span> <span class="o">isnt</span> <span class="s1">&#39;.coffee&#39;</span>
<span class="k">return</span> <span class="nx">compile</span> <span class="s2">&quot;#{source}.coffee&quot;</span><span class="p">,</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">topLevel</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">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
<span class="nx">trackUnprocessedFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">files</span><span class="p">.</span><span class="nx">length</span>
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span>
<span class="nx">compile</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">)</span>
<span class="nx">compile</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">),</span> <span class="nx">sourceIndex</span>
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;.coffee&#39;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="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">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">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">contents</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">=</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">sourceIndex</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">join</span><span class="p">(</span><span class="s1">&#39;\n&#39;</span><span class="p">)</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">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</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>
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">true</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 a single source script, containing the given code, according to the
<span class="k">else</span>
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</span>
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">),</span> <span class="kc">true</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 a single source script, containing the given code, according to the
requested options. If evaluating the script directly sets <code>__filename</code>,
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScript = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o = </span><span class="nx">opts</span>
@@ -90,7 +118,7 @@ requested options. If evaluating the script directly sets <code>__filename</code
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;failure&#39;</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s1">&#39;failure&#39;</span><span class="p">).</span><span class="nx">length</span>
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">printWarn</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span>
<span class="nx">printWarn</span> <span class="nx">err</span> <span class="k">instanceof</span> <span class="nb">Error</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="s2">&quot;ERROR: #{err}&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileStdio = </span><span class="o">-&gt;</span>
<span class="nv">code = </span><span class="s1">&#39;&#39;</span>
@@ -101,18 +129,25 @@ 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>
<span class="nv">module.filename = </span><span class="nx">realFilename</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>Watch a source CoffeeScript file using <code>fs.watchFile</code>, recompiling it every
<span class="nv">module.filename = </span><span class="nx">realFilename</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>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
time the file is updated. May be used in combination with other options,
such as <code>--lint</code> or <code>--print</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watch = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">watchFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">{</span><span class="nx">persistent</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">interval</span><span class="o">:</span> <span class="mi">500</span><span class="p">},</span> <span class="p">(</span><span class="nx">curr</span><span class="p">,</span> <span class="nx">prev</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="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">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</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></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
<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">prevStats</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="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">event</span> <span class="o">is</span> <span class="s1">&#39;change&#39;</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">return</span> <span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span>
<span class="nx">stats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span>
<span class="nv">prevStats = </span><span class="nx">stats</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="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">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</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></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
directory can be customized with <code>--output</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">writeJs = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">filename = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s1">&#39;.js&#39;</span>
@@ -126,12 +161,12 @@ 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>
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s1">&#39;:\t&#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="nx">trim</span><span class="p">()</span>
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/../extras/jsl.conf&#39;</span>
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/../../extras/jsl.conf&#39;</span>
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">&#39;jsl&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;-nologo&#39;</span><span class="p">,</span> <span class="s1">&#39;-stdin&#39;</span><span class="p">,</span> <span class="s1">&#39;-conf&#39;</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>

View File

@@ -53,7 +53,7 @@ all parsing must end here.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s1">&#39;STATEMENT&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</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>All the different types of expressions in our language. The basic unit of
CoffeeScript is the <strong>Expression</strong> -- everything that can be an expression
is one. Block serve as the building blocks of many other rules, making
is one. Blocks serve as the building blocks of many other rules, making
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Expression</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Value&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Invocation&#39;</span>
@@ -77,7 +77,7 @@ token stream.</p> </td> <td class="code">
they can also serve as keys in object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">AlphaNumeric</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</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>All of our immediate values. These can (in general), be passed straight
<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>All of our immediate values. Generally these can be passed straight
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Literal</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;AlphaNumeric&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;JS&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
@@ -128,91 +128,92 @@ that hoovers up the remaining arguments.</p> </td> <td c
<span class="nx">o</span> <span class="s1">&#39;ParamVar&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;ParamVar ...&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">on</span>
<span class="nx">o</span> <span class="s1">&#39;ParamVar = Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span>
<span class="nx">ParamVar</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Function Parameters</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ParamVar</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Identifier&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;ThisProperty&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Array&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Object&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Splat</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Splat</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">Splat</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleAssignable</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleAssignable</span><span class="o">:</span> <span class="p">[</span>
<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">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Value Accessor&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;Value Accessor&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;Invocation Accessor&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
<span class="nx">o</span> <span class="s1">&#39;ThisProperty&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Assignable</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Assignable</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;SimpleAssignable&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Array&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Object&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>The types of things that can be treated as values -- assigned to, invoked
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>The types of things that can be treated as values -- assigned to, invoked
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Value</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Assignable&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Literal&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Parenthetical&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Range&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;This&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>The general group of accessors into an object, by property, by prototype
<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>The general group of accessors into an object, by property, by prototype
or by array index or slice.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Accessor</span><span class="o">:</span> <span class="p">[</span>
<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="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;soak&#39;</span>
<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;:: Identifier&#39;</span><span class="p">,</span> <span class="o">-&gt;</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;prototype&#39;</span><span class="p">),</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">]</span>
<span class="nx">o</span> <span class="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="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>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 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></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="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-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#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
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>Assignment of properties within an object literal can be separated by
comma, as in JavaScript, or simply by newline.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">AssignList</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s1">&#39;AssignObj&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s1">&#39;AssignList , AssignObj&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;AssignList OptComma TERMINATOR AssignObj&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;AssignList OptComma INDENT AssignList OptComma OUTDENT&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Class</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</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;CLASS EXTENDS Value&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS EXTENDS Value Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS SimpleAssignable&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS SimpleAssignable Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</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;CLASS SimpleAssignable EXTENDS Value&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS SimpleAssignable EXTENDS Value Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Invocation</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</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;CLASS EXTENDS Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS EXTENDS Expression Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS SimpleAssignable&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS SimpleAssignable Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</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;CLASS SimpleAssignable EXTENDS Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;CLASS SimpleAssignable EXTENDS Expression Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Invocation</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Value OptFuncExist Arguments&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Call</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;Invocation OptFuncExist Arguments&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Call</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;SUPER&#39;</span><span class="p">,</span> <span class="o">-&gt;</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="nx">o</span> <span class="s1">&#39;SUPER Arguments&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Call</span> <span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptFuncExist</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptFuncExist</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="kc">no</span>
<span class="nx">o</span> <span class="s1">&#39;FUNC_EXIST&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arguments</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arguments</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;CALL_START CALL_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s1">&#39;CALL_START ArgList OptComma CALL_END&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">This</span><span class="o">:</span> <span class="p">[</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>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">This</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;THIS&#39;</span><span class="p">,</span> <span class="o">-&gt;</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;this&#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">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;this&#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>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ThisProperty</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</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>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ThisProperty</span><span class="o">:</span> <span class="p">[</span>
<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">Value</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s1">&#39;this&#39;</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">$2</span><span class="p">)],</span> <span class="s1">&#39;this&#39;</span>
<span class="p">]</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 array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;[ ]&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Arr</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s1">&#39;[ ArgList OptComma ]&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Arr</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>Inclusive and exclusive range dots.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">RangeDots</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>Inclusive and exclusive range dots.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">RangeDots</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;..&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="s1">&#39;inclusive&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;...&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="s1">&#39;exclusive&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>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="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>The 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="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,
<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>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;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-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">&#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>
<span class="nx">o</span> <span class="s1">&#39;Arg&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
@@ -220,35 +221,35 @@ as well as the contents of an array literal
<span class="nx">o</span> <span class="s1">&#39;ArgList OptComma TERMINATOR Arg&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;INDENT ArgList OptComma OUTDENT&#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;ArgList OptComma INDENT ArgList OptComma OUTDENT&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">&#182;</a> </div> <p>Valid arguments are Block or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arg</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">&#182;</a> </div> <p>Valid arguments are Blocks or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arg</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Expression&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Splat&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">&#182;</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">&#182;</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleArgs</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Expression&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;SimpleArgs , Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">&#182;</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Try</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">&#182;</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Try</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;TRY Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;TRY Block Catch&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s1">&#39;TRY Block FINALLY Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;TRY Block Catch FINALLY Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">&#182;</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;CATCH Identifier Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</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>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;THROW Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Throw</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">&#182;</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
not an <strong>Expression</strong>, so if you need to use an expression in a place
where only values are accepted, wrapping it in parentheses will always do
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Parenthetical</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;( Body )&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;( INDENT Body OUTDENT )&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;WHILE Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;WHILE Expression WHEN Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s1">&#39;UNTIL Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s1">&#39;UNTIL Expression WHEN Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">&#182;</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">While</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;WhileSource Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;Statement WhileSource&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
@@ -259,7 +260,7 @@ or postfix, with a single expression. There is no do..while.</p> </t
<span class="nx">Loop</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;LOOP Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;true&#39;</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;LOOP Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s1">&#39;true&#39;</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">&#182;</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">&#182;</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
Comprehensions can either be normal, with a block of expressions to execute,
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">For</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Statement ForBody&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
@@ -275,17 +276,17 @@ or postfix, with a single expression.</p> </td> <td clas
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;FOR ForVariables&#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;FOR OWN ForVariables&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nv">$3.own = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">&#182;</a> </div> <p>An array of all accepted values for a variable inside the loop.
<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>An array of all accepted values for a variable inside the loop.
This enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForValue</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;Identifier&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Array&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Object&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>An array or range comprehension has variables for the current element
<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>An array or range comprehension has variables for the current element
and (optional) reference to the current index. Or, <em>key, value</em>, in the case
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForVariables</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;ForValue&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s1">&#39;ForValue , ForValue&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="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>The source of a comprehension is an array or object with an optional guard
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">&#182;</a> </div> <p>The source of a comprehension is an array or object with an optional guard
clause. If it's an array comprehension, you can also choose to step through
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForSource</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;FORIN Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span>
@@ -307,21 +308,21 @@ in fixed-size increments.</p> </td> <td class="code">
<span class="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;When&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;Whens When&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">&#182;</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">&#182;</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;LEADING_WHEN SimpleArgs Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
<span class="nx">o</span> <span class="s1">&#39;LEADING_WHEN SimpleArgs Block TERMINATOR&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">&#182;</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">&#182;</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
if-related rules are broken up along these lines in order to avoid
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">IfBlock</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;IF Expression Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;IfBlock ELSE IF Expression Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">&#182;</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
<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> <p>The full complement of <em>if</em> expressions, including postfix one-liner
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">If</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s1">&#39;IfBlock&#39;</span>
<span class="nx">o</span> <span class="s1">&#39;IfBlock ELSE Block&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;Statement POST_IF Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s1">&#39;Expression POST_IF Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</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> <p>Arithmetic and logical operators, working on one or more operands.
<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> <p>Arithmetic and logical operators, working on one or more operands.
Here they are grouped by order of precedence. The actual precedence rules
are defined at the bottom of the page. It would be shorter if we could
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
@@ -334,7 +335,7 @@ rules are necessary.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s1">&#39;-- SimpleAssignable&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;++ SimpleAssignable&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;SimpleAssignable --&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s1">&#39;SimpleAssignable ++&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">&#182;</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">o</span> <span class="s1">&#39;Expression ?&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;SimpleAssignable ++&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">&#182;</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">o</span> <span class="s1">&#39;Expression ?&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s1">&#39;Expression + Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;+&#39;</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s1">&#39;Expression - Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">&#39;-&#39;</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
@@ -354,7 +355,7 @@ rules are necessary.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s1">&#39;SimpleAssignable COMPOUND_ASSIGN</span>
<span class="s1"> INDENT Expression OUTDENT&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s1">&#39;SimpleAssignable EXTENDS Expression&#39;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">&#182;</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">&#182;</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">&#182;</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<pre><code>2 + (3 * 4)
@@ -380,7 +381,7 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<span class="p">[</span><span class="s1">&#39;right&#39;</span><span class="p">,</span> <span class="s1">&#39;FORIN&#39;</span><span class="p">,</span> <span class="s1">&#39;FOROF&#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="p">[</span><span class="s1">&#39;right&#39;</span><span class="p">,</span> <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;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;DO&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#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;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;right&#39;</span><span class="p">,</span> <span class="s1">&#39;POST_IF&#39;</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">&#182;</a> </div> <p>Finally, now what we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">&#182;</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">&#182;</a> </div> <p>Finally, now that we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
terminals (every symbol which does not appear as the name of a rule above)
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tokens = </span><span class="p">[]</span>
@@ -389,7 +390,7 @@ as "tokens".</p> </td> <td class="code"> <
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">&#39; &#39;</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="nx">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
<span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;return #{alt[1]}&quot;</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s1">&#39;Root&#39;</span>
<span class="nx">alt</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>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">&#182;</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
rules, and the name of the root. Reverse the operators because Jison orders
precedence from low to high, and we have it high to low
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.parser = </span><span class="k">new</span> <span class="nx">Parser</span>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -13,17 +13,20 @@ option) list, and all subsequent arguments are left unparsed.</p> </
<p>Along with an an optional banner for the usage help.</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">rules</span><span class="p">,</span> <span class="nx">@banner</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@rules = </span><span class="nx">buildRules</span> <span class="nx">rules</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>Parse the list of arguments, populating an <code>options</code> object with all of the
specified options, and returning it. <code>options.arguments</code> will be an array
specified options, and return it. <code>options.arguments</code> will be an array
containing the remaining non-option arguments. <code>options.literals</code> will be
an array of options that are meant to be passed through directly to the
executing script. This is a simpler API than many option parsers that allow
you to attach callback actions for every flag. Instead, you're responsible
for interpreting the options object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">parse</span><span class="o">:</span> <span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">options = </span><span class="nx">arguments</span><span class="o">:</span> <span class="p">[],</span> <span class="nx">literals</span><span class="o">:</span> <span class="p">[]</span>
<span class="nv">args = </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
<span class="nv">originalArgs = </span><span class="nx">args</span>
<span class="nv">args = </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
<span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">args</span>
<span class="k">if</span> <span class="nx">arg</span> <span class="o">is</span> <span class="s1">&#39;--&#39;</span>
<span class="nv">options.literals = </span><span class="nx">args</span><span class="p">[(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)..]</span>
<span class="nv">pos = </span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">&#39;--&#39;</span>
<span class="nv">options.arguments = </span><span class="p">[</span><span class="nx">originalArgs</span><span class="p">[</span><span class="mi">1</span> <span class="o">+</span> <span class="nx">pos</span><span class="p">]]</span>
<span class="nv">options.literals = </span><span class="nx">originalArgs</span><span class="p">[(</span><span class="mi">2</span> <span class="o">+</span> <span class="nx">pos</span><span class="p">)..]</span>
<span class="k">break</span>
<span class="nv">isOption = </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span>
<span class="nv">matchedRule = </span><span class="kc">no</span>
@@ -35,7 +38,7 @@ for interpreting the options object.</p> </td> <td class
<span class="k">break</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;unrecognized option: #{arg}&quot;</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">isOption</span>
<span class="nv">options.arguments = </span><span class="nx">args</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">i</span>
<span class="nv">options.arguments = </span><span class="nx">originalArgs</span><span class="p">[(</span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">arg</span><span class="p">)..]</span>
<span class="k">break</span>
<span class="nx">options</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>Return the help text for this <strong>OptionParser</strong>, listing and describing all
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">help</span><span class="o">:</span> <span class="o">-&gt;</span>

View File

@@ -4,26 +4,80 @@ 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>
<span class="nv">Module = </span><span class="nx">require</span> <span class="s1">&#39;module&#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">REPL_PROMPT = </span><span class="s1">&#39;coffee&gt; &#39;</span>
<span class="nv">REPL_PROMPT_CONTINUATION = </span><span class="s1">&#39;......&gt; &#39;</span>
<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&#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">if</span> <span class="o">!</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span> <span class="o">and</span> <span class="o">!</span><span class="nx">backlog</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
<span class="k">return</span>
<span class="nv">code = </span><span class="nx">backlog</span> <span class="o">+=</span> <span class="nx">buffer</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="nv">backlog = </span><span class="s2">&quot;#{backlog[...-1]}\n&quot;</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT_CONTINUATION</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
<span class="k">return</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</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">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="nv">_ = </span><span class="nx">global</span><span class="p">.</span><span class="nx">_</span>
<span class="nv">returnValue = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="s2">&quot;_=(#{code}\n)&quot;</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">filename</span><span class="o">:</span> <span class="s1">&#39;repl&#39;</span>
<span class="nx">modulename</span><span class="o">:</span> <span class="s1">&#39;repl&#39;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="nx">returnValue</span> <span class="o">is</span> <span class="kc">undefined</span>
<span class="nv">global._ = </span><span class="nx">_</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">returnValue</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-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>
<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="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">prefix</span><span class="p">,</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</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="nv">free = </span><span class="p">(</span><span class="nx">text</span><span class="p">.</span><span class="nx">match</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="k">if</span> <span class="nx">free</span><span class="o">?</span>
<span class="nv">vars = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="s1">&#39;Object.getOwnPropertyNames(this)&#39;</span>
<span class="nv">keywords = </span><span class="p">(</span><span class="nx">r</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">RESERVED</span> <span class="k">when</span> <span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">&#39;__&#39;</span><span class="p">)</span>
<span class="nv">possibilities = </span><span class="nx">vars</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">keywords</span>
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">free</span><span class="p">,</span> <span class="nx">possibilities</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>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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#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>
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;line&#39;</span><span class="p">,</span> <span class="nx">run</span>
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;attemptClose&#39;</span><span class="p">,</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">backlog</span>
<span class="nv">backlog = </span><span class="s1">&#39;&#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="s1">&#39;\n&#39;</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
<span class="k">else</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">close</span><span class="p">()</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">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s1">&#39;\n&#39;</span>
<span class="nx">stdin</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;line&#39;</span><span class="p">,</span> <span class="nx">run</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -3,7 +3,7 @@ and shorthand syntax. This can greatly complicate a grammar and bloat
the resulting parse table. Instead of making the parser handle it all, we take
a series of passes over the token stream, using this <strong>Rewriter</strong> to convert
shorthand into the unambiguous long form, add implicit indentation and
parentheses, balance incorrect nestings, and generally clean things up.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
parentheses, and generally clean things up.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Helpful snippet for debugging:
console.log (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Rewrite the token stream in multiple passes, one logical filter at
a time. This could certainly be changed into a single pass through the
@@ -18,8 +18,6 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
<span class="nx">@tagPostfixConditionals</span><span class="p">()</span>
<span class="nx">@addImplicitBraces</span><span class="p">()</span>
<span class="nx">@addImplicitParentheses</span><span class="p">()</span>
<span class="nx">@ensureBalance</span> <span class="nx">BALANCED_PAIRS</span>
<span class="nx">@rewriteClosingParens</span><span class="p">()</span>
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
Allow the return value of the block to tell us how many tokens to move
forwards (or backwards) in the stream, to make sure we don't miss anything
@@ -78,7 +76,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>
@@ -101,19 +102,19 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
Insert the implicit parentheses here, so that the parser doesn't have to
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitParentheses</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nv">noCall = </span><span class="kc">no</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">idx = </span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;OUTDENT&#39;</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_END&#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="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;CALL_END&#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="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="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">noCall = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;CLASS&#39;</span><span class="p">,</span> <span class="s1">&#39;IF&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">current</span><span class="p">,</span> <span class="nx">next</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span>
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;{&#39;</span> <span class="o">and</span>
<span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span>
<span class="nv">seenSingle = </span><span class="kc">no</span>
<span class="nv">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="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span>
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;{&#39;</span> <span class="o">and</span>
<span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span>
<span class="nv">seenSingle = </span><span class="kc">no</span>
<span class="nv">seenControl = </span><span class="kc">no</span>
<span class="nv">noCall = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="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>
@@ -121,9 +122,11 @@ deal with them.</p> </td> <td class="code">
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="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="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
<span class="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#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="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;CATCH&#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="nv">seenControl = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="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;TRY&#39;</span><span class="p">]</span>
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="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">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;OUTDENT&#39;</span>
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;,&#39;</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">and</span>
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;,&#39;</span> <span class="o">and</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">seenControl</span><span class="p">))</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;CLASS&#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">not</span> <span class="k">in</span> <span class="nx">IMPLICIT_BLOCK</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">((</span><span class="nv">post = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;{&#39;</span><span class="p">)))</span>
@@ -167,64 +170,8 @@ different precedence.</p> </td> <td class="code">
<span class="nv">original = </span><span class="nx">token</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="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">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;POST_&#39;</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">&#39;INDENT&#39;</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout
the course of the token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ensureBalance</span><span class="o">:</span> <span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">levels = </span><span class="p">{}</span>
<span class="nv">openLine = </span><span class="p">{}</span>
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">@tokens</span>
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
<span class="k">for</span> <span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span> <span class="k">in</span> <span class="nx">pairs</span>
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">|=</span> <span class="mi">0</span>
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">open</span>
<span class="nx">openLine</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">++</span> <span class="o">is</span> <span class="mi">0</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">close</span> <span class="o">and</span> <span class="o">--</span><span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">0</span>
<span class="k">throw</span> <span class="nb">Error</span> <span class="s2">&quot;too many #{token[1]} on line #{token[2] + 1}&quot;</span>
<span class="k">for</span> <span class="nx">open</span><span class="p">,</span> <span class="nx">level</span> <span class="k">of</span> <span class="nx">levels</span> <span class="k">when</span> <span class="nx">level</span> <span class="o">&gt;</span> <span class="mi">0</span>
<span class="k">throw</span> <span class="nb">Error</span> <span class="s2">&quot;unclosed #{ open } on line #{openLine[open] + 1}&quot;</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>We'd like to support syntax like this:</p>
<pre><code>el.click((event) -&gt;
el.hide())
</code></pre>
<p>In order to accomplish this, move outdents that follow closing parens
inwards, safely. The steps to accomplish this are:</p>
<ol>
<li>Check that all paired tokens are balanced and in order.</li>
<li>Rewrite the stream with a stack: if you see an <code>EXPRESSION_START</code>, add it
to the stack. If you see an <code>EXPRESSION_END</code>, pop the stack and replace
it with the inverse of what we've just popped.</li>
<li>Keep track of "debt" for tokens that we manufacture, to make sure we end
up balanced in the end.</li>
<li>Be careful not to alter array or parentheses delimiters with overzealous
rewriting.</li>
</ol> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">rewriteClosingParens</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nv">stack = </span><span class="p">[]</span>
<span class="nv">debt = </span><span class="p">{}</span>
<span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="nx">key</span> <span class="k">of</span> <span class="nx">INVERSES</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-&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="nx">token</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">EXPRESSION_END</span>
<span class="k">if</span> <span class="nx">debt</span><span class="p">[</span><span class="nv">inv = </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">tag</span><span class="p">]]</span> <span class="o">&gt;</span> <span class="mi">0</span>
<span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="nv">match = </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nv">mtag = </span><span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">oppos = </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">oppos</span>
<span class="nx">debt</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nv">val = </span><span class="p">[</span><span class="nx">oppos</span><span class="p">,</span> <span class="k">if</span> <span class="nx">mtag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="nx">oppos</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="nx">mtag</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">val</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">match</span>
<span class="k">else</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">val</span>
<span class="mi">1</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>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="mi">2</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="p">[</span><span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</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">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="mi">2</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="p">[</span><span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</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>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</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">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
<span class="p">[</span><span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</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="p">[</span><span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">]</span>
@@ -232,20 +179,20 @@ rewriting.</li>
<span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s1">&#39;PARAM_END&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;INDEX_START&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
<span class="nv">EXPRESSION_END = </span><span class="p">[]</span>
<span class="k">for</span> <span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">rite</span><span class="p">]</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
<span class="nx">EXPRESSION_START</span><span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">rite</span><span class="p">]</span> <span class="o">=</span> <span class="nx">left</span>
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;THIS&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;THIS&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
<span class="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;JS&#39;</span><span class="p">,</span> <span class="s1">&#39;REGEX&#39;</span><span class="p">,</span> <span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s1">&#39;CLASS&#39;</span>
<span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s1">&#39;THIS&#39;</span><span class="p">,</span> <span class="s1">&#39;BOOL&#39;</span><span class="p">,</span> <span class="s1">&#39;UNARY&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span>
<span class="s1">&#39;@&#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;[&#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="s1">&#39;++&#39;</span>
<span class="p">]</span>
<span class="nv">IMPLICIT_UNSPACED_CALL = </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></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#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></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">&#39;POST_IF&#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;UNTIL&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;BY&#39;</span><span class="p">,</span> <span class="s1">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
<span class="nv">IMPLICIT_UNSPACED_CALL = </span><span class="p">[</span><span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#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></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">&#39;POST_IF&#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;UNTIL&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;BY&#39;</span><span class="p">,</span> <span class="s1">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS = </span><span class="p">[</span><span class="s1">&#39;ELSE&#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;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s1">&#39;THEN&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#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="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#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="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">]</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -6,9 +6,9 @@ variables are new and need to be declared with <code>var</code>, and which are s
with the outside.</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>Import the helpers we plan to use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">,</span> <span class="nx">last</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">&#39;./helpers&#39;</span>
<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
as well as a reference to the <strong>Block</strong> node it belongs to, which is
where it should declare its variables, and a reference to the function that
it wraps.</p> </td> <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

@@ -64,7 +64,7 @@
<a href="#regexes">Extended Regular Expressions</a>
<a href="#cake">Cake, and Cakefiles</a>
<a href="#scripts">"text/coffeescript" Script Tags</a>
<a href="#resources">Examples and Resources</a>
<a href="#resources">Books, Screencasts, Examples and Resources</a>
<a href="#change_log">Change Log</a>
</div>
</div>
@@ -80,10 +80,11 @@
<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>
<a class="minibutton permalink" id="repl_permalink">Link</a>
<br class="clear" />
</div>
</div>
@@ -114,7 +115,7 @@
<p>
<b>CoffeeScript is a little language that compiles into JavaScript.</b> Underneath
all of those embarrassing braces and semicolons, JavaScript has always had
all those awkward braces and semicolons, JavaScript has always had
a gorgeous object model at its heart. CoffeeScript is an attempt to expose
the good parts of JavaScript in a simple way.
</p>
@@ -123,15 +124,16 @@
The golden rule of CoffeeScript is: <i>"It's just JavaScript"</i>. The code
compiles one-to-one into the equivalent JS, and there is
no interpretation at runtime. You can use any existing JavaScript library
seamlessly (and vice-versa). The compiled output is readable and pretty-printed,
passes through <a href="http://www.javascriptlint.com/">JavaScript Lint</a>
seamlessly from CoffeeScript (and vice-versa). The compiled output is
readable and pretty-printed, passes through
<a href="http://www.javascriptlint.com/">JavaScript Lint</a>
without warnings, will work in every JavaScript implementation, and tends
to run as fast or faster than the equivalent handwritten JavaScript.
</p>
<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.3">1.1.3</a>
</p>
<h2>
@@ -166,17 +168,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>
@@ -185,7 +191,9 @@ sudo bin/cake install</pre>
If installing on Ubuntu or Debian,
<a href="http://opinionated-programmer.com/2010/12/installing-coffeescript-on-debian-or-ubuntu/">be
careful not to use the existing out-of-date package</a>. If installing on
Windows, your best bet is probably to run Node.js under Cygwin.
Windows, your best bet is probably to run Node.js under Cygwin. If you'd
just like to experiment, you can try the
<a href="https://github.com/alisey/CoffeeScript-Compiler-for-Windows">CoffeeScript Compiler For Windows</a>.
</p>
<p>
@@ -207,8 +215,7 @@ sudo bin/cake install</pre>
<td width="25%"><code>-i, --interactive</code></td>
<td>
Launch an interactive CoffeeScript session to try short snippets.
More pleasant if wrapped with
<a href="http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap.html">rlwrap</a>.
Identical to calling <tt>coffee</tt> with no arguments.
</td>
</tr>
<tr>
@@ -219,17 +226,18 @@ 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>
<td><code>-w, --watch</code></td>
<td>
Watch the modification times of the coffee-scripts, recompiling as
soon as a change occurs.
Watch files for changes, rerunning the specified command when any
file is updated.
</td>
</tr>
<tr>
@@ -261,7 +269,7 @@ sudo bin/cake install</pre>
<td><code>-e, --eval</code></td>
<td>
Compile and print a little snippet of CoffeeScript directly from the
command line. For example:<br /><tt>coffee -e "puts num for num in [10..1]"</tt>
command line. For example:<br /><tt>coffee -e "console.log num for num in [10..1]"</tt>
</td>
</tr>
<tr>
@@ -274,8 +282,8 @@ sudo bin/cake install</pre>
<tr>
<td><code>-b, --bare</code></td>
<td>
Compile the JavaScript without the top-level function safety wrapper.
(Used for CoffeeScript as a Node.js module.)
Compile the JavaScript without the
<a href="#lexical_scope">top-level function safety wrapper</a>.
</td>
</tr>
<tr>
@@ -304,7 +312,7 @@ Expressions
<td><code>--nodejs</code></td>
<td>
The <tt>node</tt> executable has some useful options you can set,
such as<br /> <tt>--debug</tt> and <tt>--max-stack-size</tt>. Use this
such as<br /> <tt>--debug</tt>, <tt>--debug-brk</tt> and <tt>--max-stack-size</tt>. Use this
flag to forward options directly to Node.js.
</td>
</tr>
@@ -316,9 +324,9 @@ Expressions
<ul>
<li>
Compile a directory tree of <tt>.coffee</tt> files into a parallel
tree of <tt>.js</tt>, in <tt>lib</tt>:<br />
<tt>coffee -o lib/ -c src/</tt>
Compile a directory tree of <tt>.coffee</tt> files in <tt>src</tt> into a parallel
tree of <tt>.js</tt> files in <tt>lib</tt>:<br />
<tt>coffee --compile --output lib/ src/</tt>
</li>
<li>
Watch a file for changes, and recompile it every time the file is saved:<br />
@@ -326,12 +334,16 @@ 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 />
<tt>coffee -bpe "alert i for i in [0..10]"</tt>
</li>
<li>
All together now, watch and recompile an entire project as you work on it:<br />
<tt>coffee -o lib/ -cw src/</tt>
</li>
<li>
Start the CoffeeScript REPL:<br />
<tt>coffee</tt>
@@ -362,8 +374,8 @@ Expressions
<p>
First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code.
You don't need to use semicolons <tt>;</tt> to terminate expressions,
ending the line will do just as well, (although semicolons can still
be used to fit multiple expressions onto a single line.)
ending the line will do just as well (although semicolons can still
be used to fit multiple expressions onto a single line).
Instead of using curly braces
<tt>{ }</tt> to surround blocks of code in <a href="#functions">functions</a>,
<a href="#conditionals">if-statements</a>,
@@ -442,7 +454,7 @@ Expressions
If you'd like to create top-level variables for other scripts to use,
attach them as properties on <b>window</b>, or on the <b>exports</b>
object in CommonJS. The <b>existential operator</b> (covered below), gives you a
reliable way to figure out where to add them, if you're targeting both
reliable way to figure out where to add them; if you're targeting both
CommonJS and the browser: <tt>exports ? this</tt>
</p>
@@ -497,7 +509,7 @@ Expressions
each iteration into an array. Sometimes functions end with loops that are
intended to run only for their side-effects. Be careful that you're not
accidentally returning the results of the comprehension in these cases,
by adding a meaningful return value, like <tt>true</tt>, or <tt>null</tt>,
by adding a meaningful return value &mdash; like <tt>true</tt> &mdash; or <tt>null</tt>,
to the bottom of your function.
</p>
<p>
@@ -542,7 +554,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>
@@ -560,7 +572,7 @@ Expressions
to CoffeeScript functions, they nonetheless return their final value.
The CoffeeScript compiler tries to make sure that all statements in the
language can be used as expressions. Watch how the <tt>return</tt> gets
pushed down into each possible branch of execution, in the function
pushed down into each possible branch of execution in the function
below.
</p>
<%= code_for('expressions', 'eldest') %>
@@ -620,7 +632,7 @@ Expressions
are the same as boolean <tt>true</tt>, while <tt>off</tt> and <tt>no</tt> are boolean <tt>false</tt>.
</p>
<p>
For single-line statements, <tt>unless</tt> can be used as the inverse of <tt>if</tt>.
<tt>unless</tt> can be used as the inverse of <tt>if</tt>.
</p>
<p>
As a shortcut for <tt>this.property</tt>, you can use <tt>@property</tt>.
@@ -701,20 +713,20 @@ 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()') %>
<p>
Finally class definitions are blocks of executable code, which make for interesting
Finally, class definitions are blocks of executable code, which make for interesting
metaprogramming possibilities. Because in the context of a class definition,
<tt>this</tt> is the class object itself (the constructor function), you
can assign static properties by using <br /><tt>@property: value</tt>, and call
@@ -753,7 +765,7 @@ Expressions
<b class="header">Function binding</b>
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
object that the current function is attached to. If you pass a function as
as callback, or attach it to a different object, the original value of <tt>this</tt>
a callback or attach it to a different object, the original value of <tt>this</tt>
will be lost. If you're not familiar with this behavior,
<a href="http://www.digital-web.com/articles/scope_in_javascript/">this Digital Web article</a>
gives a good overview of the quirks.
@@ -835,14 +847,14 @@ Expressions
indentation level that begins the heredoc is maintained throughout, so
you can keep it all aligned with the body of your code.
</p>
<%= code_for('heredocs') %>
<%= code_for('heredocs', 'html') %>
<p>
Double-quoted heredocs, like double-quoted strings, allow interpolation.
</p>
<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') %>
@@ -865,13 +877,13 @@ Expressions
</h2>
<p>
CoffeeScript includes a simple build system similar to
CoffeeScript includes a (very) simple build system similar to
<a href="http://www.gnu.org/software/make/">Make</a> and
<a href="http://rake.rubyforge.org/">Rake</a>. Naturally,
it's called Cake, and is used for the build and test tasks for the CoffeeScript
it's called Cake, and is used for the tasks that build and test the CoffeeScript
language itself. Tasks are defined in a file named <tt>Cakefile</tt>, and
can be invoked by running <tt>cake taskname</tt> from within the directory.
To print a list of all the tasks and options, just run <tt>cake</tt>.
can be invoked by running <tt>cake [task]</tt> from within the directory.
To print a list of all the tasks and options, just type <tt>cake</tt>.
</p>
<p>
@@ -886,7 +898,11 @@ Expressions
<p>
If you need to invoke one task before another &mdash; for example, running
<tt>build</tt> before <tt>test</tt>, you can use the <tt>invoke</tt> function:
<tt>invoke 'build'</tt>
<tt>invoke 'build'</tt>. Cake tasks are a minimal way to expose your
CoffeeScript functions to the command line, so
<a href="documentation/docs/cake.html">don't expect any fanciness built-in</a>.
If you need dependencies, or async callbacks, it's best to put them in your
code itself &mdash; not the cake task.
</p>
<h2>
@@ -905,7 +921,7 @@ Expressions
<p>
In fact, the little bit of glue script that runs "Try CoffeeScript" above,
as well as jQuery for the menu, is implemented in just this way.
as well as the jQuery for the menu, is implemented in just this way.
View source and look at the bottom of the page to see the example.
Including the script also gives you access to <tt>CoffeeScript.compile()</tt>
so you can pop open Firebug and try compiling some strings.
@@ -919,10 +935,69 @@ Expressions
<h2>
<span id="resources" class="bookmark"></span>
Examples
Books and Screencasts
</h2>
<p>
There are a number of excellent books and screencasts to help you get
started with CoffeeScript, some of which are freely available online.
</p>
<ul>
<li>
<a href="http://arcturo.github.com/library/coffeescript/">The Little Book on CoffeeScript</a>
is a brief 5-chapter introduction to CoffeeScript, written with great
clarity and precision by
<a href="http://alexmaccaw.co.uk/">Alex MacCaw</a>.
</li>
<li>
<a href="http://autotelicum.github.com/Smooth-CoffeeScript/">Smooth CoffeeScript</a>
is a reimagination of the excellent book
<a href="http://eloquentjavascript.net/">Eloquent JavaScript</a>, as if
it had been written in CoffeeScript instead. Covers language features
as well a the functional and object oriented programming styles. By
<a href="https://github.com/autotelicum">E. Hoigaard</a>.
</li>
<li>
<a href="http://pragprog.com/book/tbcoffee/coffeescript">CoffeeScript: Accelerated JavaScript Development</a>
is <a href="http://trevorburnham.com/">Trevor Burnham</a>'s thorough
introduction to the language. By the end of the book, you'll have built
a fast-paced multiplayer word game, writing both the client-side and Node.js
portions in CoffeeScript.
</li>
<li>
<a href="http://peepcode.com/products/coffeescript">Meet CoffeeScript</a>
is a 75-minute long screencast by <a href="http://peepcode.com/">PeepCode</a>.
Highly memorable for its animations which demonstrate transforming CoffeeScript
into the equivalent JS.
</li>
<li>
If you're looking for less of a time commitment, RailsCasts'
<a href="http://railscasts.com/episodes/267-coffeescript-basics">CoffeeScript Basics</a>
should have you covered, hitting all of the important notes about CoffeeScript
in 11 minutes.
</li>
</ul>
<h2>
Examples
</h2>
<p>
The <a href="https://github.com/languages/coffeescript">best list of
open-source CoffeeScript examples</a> can be found on GitHub. But just
to throw out few more:
</p>
<ul>
<li>
<b>github</b>'s <a href="http://hubot.github.com/">Hubot</a>,
a friendly IRC robot that can perform any number of useful and useless tasks.
</li>
<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 +1007,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 +1024,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 +1046,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 +1086,99 @@ Expressions
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.2...1.1.3">1.1.3</a>
<span class="timestamp"> &ndash; <small>Nov. 8, 2011</small></span>
</b>
<ul>
<li>
Ahh, whitespace. CoffeeScript's compiled JS now tries to space things
out and keep it readable, as you can see in the examples on this page.
</li>
<li>
You can now call <tt>super</tt> in class level methods in class bodies,
and bound class methods now preserve their correct context.
</li>
<li>
JavaScript has always supported octal numbers <tt>010 is 8</tt>,
and hexadecimal numbers <tt>0xf is 15</tt>, but CoffeeScript now
also supports binary numbers: <tt>0b10 is 2</tt>.
</li>
<li>
The CoffeeScript module has been nested under a subdirectory to make
it easier to <tt>require</tt> individual components separately, without
having to use <b>npm</b>. For example, after adding the CoffeeScript
folder to your path: <tt>require('coffee-script/lexer')</tt>
</li>
<li>
There's a new "link" feature in Try CoffeeScript on this webpage. Use
it to get a shareable permalink for your example script.
</li>
<li>
The <tt>coffee --watch</tt> feature now only works on Node.js 0.6.0
and higher, but now also works properly on Windows.
</li>
<li>
Lots of small bug fixes from
<b><a href="https://github.com/michaelficarra">@michaelficarra</a></b>,
<b><a href="https://github.com/geraldalewis">@geraldalewis</a></b>,
<b><a href="https://github.com/satyr">@satyr</a></b>, and
<b><a href="https://github.com/trevorburnham">@trevorburnham</a></b>.
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.1...1.1.2">1.1.2</a>
<span class="timestamp"> &ndash; <small>August 4, 2011</small></span>
</b>
Fixes for block comment formatting, <tt>?=</tt> compilation, implicit calls
against control structures, implicit invocation of a try/catch block,
variadic arguments leaking from local scope, line numbers in syntax errors
following heregexes, property access on parenthesized number literals,
bound class methods and super with reserved names, a REPL overhaul,
consecutive compiled semicolons, block comments in implicitly called objects,
and a Chrome bug.
</p>
<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 the <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>
@@ -1556,6 +1635,7 @@ Expressions
</div>
<script type="text/coffeescript">
sourceFragment = "try:"
# Set up the compilation function, to run when you stop typing.
compileSource = ->
@@ -1572,11 +1652,14 @@ Expressions
catch error
$('#error').text(error.message).show()
# Update permalink
$('#repl_permalink').attr 'href', "##{sourceFragment}#{encodeURIComponent source}"
# Listen for keypresses and recompile.
$('#repl_source').keyup -> compileSource()
# Eval the compiled js.
$('.minibutton.run').click ->
evalJS = ->
try
eval window.compiledJS
catch error then alert error
@@ -1592,6 +1675,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,18 +1688,34 @@ 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>')
$("#repl_permalink").click (e) ->
window.location = $(this).attr("href")
false
# If source code is included in location.hash, display it.
hash = decodeURIComponent location.hash.replace(/^#/, '')
if hash.indexOf(sourceFragment) == 0
src = hash.substr sourceFragment.length
loadConsole src
compileSource()
</script>
<script src="documentation/vendor/jquery-1.4.2.js"></script>
<script src="documentation/vendor/jquery-1.6.4.js"></script>
<script src="extras/coffee-script.js"></script>
</body>

View File

@@ -1,17 +1,13 @@
var volume, winner;
if (ignition === true) {
launch();
}
if (band !== SpinalTap) {
volume = 10;
}
if (answer !== false) {
letTheWildRumpusBegin();
}
if (car.speed < limit) {
accelerate();
}
if (pick === 47 || pick === 92 || pick === 13) {
winner = true;
}
print(inspect("My name is " + this.name));
if (ignition === true) launch();
if (band !== SpinalTap) volume = 10;
if (answer !== false) letTheWildRumpusBegin();
if (car.speed < limit) accelerate();
if (pick === 47 || pick === 92 || pick === 13) winner = true;
print(inspect("My name is " + this.name));

View File

@@ -1,6 +1,21 @@
var food, _i, _len, _ref;
var course, courses, dish, food, foods, _i, _j, _len, _len2, _len3, _ref;
_ref = ['toast', 'cheese', 'wine'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
food = _ref[_i];
eat(food);
}
}
courses = ['salad', 'entree', 'dessert'];
for (course = 0, _len2 = courses.length; course < _len2; course++) {
dish = courses[course];
menu(course + 1, dish);
}
foods = ['broccoli', 'spinach', 'chocolate'];
for (_j = 0, _len3 = foods.length; _j < _len3; _j++) {
food = foods[_j];
if (food !== 'chocolate') eat(food);
}

View File

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

View File

@@ -1,10 +1,13 @@
var fs;
fs = require('fs');
option('-o', '--output [DIR]', 'directory for compiled code');
task('build:parser', 'rebuild the Jison parser', function(options) {
var code, dir;
require('jison');
code = require('./lib/grammar').parser.generate();
dir = options.output || 'lib';
return fs.writeFile("" + dir + "/parser.js", code);
});
});

View File

@@ -1,44 +1,58 @@
var Animal, Horse, Snake, sam, tom;
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor;
child.__super__ = parent.prototype;
return child;
};
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
Animal = (function() {
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function(meters) {
return alert(this.name + " moved " + meters + "m.");
return alert(this.name + (" moved " + meters + "m."));
};
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);
};
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);
};
return Horse;
})();
sam = new Snake("Sammy the Python");
tom = new Horse("Tommy the Palomino");
sam.move();
tom.move();
tom.move();

View File

@@ -1,3 +1,5 @@
var cholesterol, healthy;
cholesterol = 127;
healthy = (200 > cholesterol && cholesterol > 60);
healthy = (200 > cholesterol && cholesterol > 60);

View File

@@ -1,12 +1,14 @@
var date, mood;
if (singing) {
mood = greatlyImproved;
}
if (singing) mood = greatlyImproved;
if (happy && knowsIt) {
clapsHands();
chaChaCha();
} else {
showIt();
}
date = friday ? sue : jill;
options || (options = defaults);
options || (options = defaults);

View File

@@ -1,7 +1,6 @@
var fill;
fill = function(container, liquid) {
if (liquid == null) {
liquid = "coffee";
}
if (liquid == null) liquid = "coffee";
return "Filling the " + container + " with " + liquid + "...";
};
};

View File

@@ -1,4 +1,5 @@
var filename, _fn, _i, _len;
_fn = function(filename) {
return fs.readFile(filename, function(err, contents) {
return compile(filename, contents.toString());
@@ -7,4 +8,4 @@ _fn = function(filename) {
for (_i = 0, _len = list.length; _i < _len; _i++) {
filename = list[_i];
_fn(filename);
}
}

View File

@@ -1,4 +1,5 @@
var hi;
hi = function() {
return [document.title, "Hello JavaScript"].join(": ");
};
};

View File

@@ -1,6 +1,9 @@
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 = 75;
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";

View File

@@ -1,4 +1,5 @@
var eldest, grade;
grade = function(student) {
if (student.excellentWork) {
return "A+";
@@ -12,4 +13,5 @@ grade = function(student) {
return "C";
}
};
eldest = 24 > 21 ? "Liz" : "Ike";
eldest = 24 > 21 ? "Liz" : "Ike";

View File

@@ -1,2 +1,3 @@
var one, six, three, two;
six = (one = 1) + (two = 2) + (three = 3);
six = (one = 1) + (two = 2) + (three = 3);

View File

@@ -1,4 +1,5 @@
var globals, name;
globals = ((function() {
var _results;
_results = [];
@@ -6,4 +7,4 @@ globals = ((function() {
_results.push(name);
}
return _results;
})()).slice(0, 10);
})()).slice(0, 10);

View File

@@ -1,7 +1,8 @@
alert((function() {
try {
return nonexistent / void 0;
} catch (error) {
return "And the error is ... " + error;
}
})());
})());

View File

@@ -1,9 +1,10 @@
var Account;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Account = function(customer, cart) {
var _this = this;
this.customer = customer;
this.cart = cart;
return $('.shopping_cart').bind('click', __bind(function(event) {
return this.customer.purchase(this.cart);
}, this));
};
return $('.shopping_cart').bind('click', function(event) {
return _this.customer.purchase(_this.cart);
});
};

View File

@@ -1,7 +1,9 @@
var cube, square;
square = function(x) {
return x * x;
};
cube = function(x) {
return square(x) * x;
};
};

View File

@@ -1,2 +1,3 @@
var html;
html = '<strong>\n cup of coffeescript\n</strong>';
html = '<strong>\n cup of coffeescript\n</strong>';

View File

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

View File

@@ -1,4 +1,7 @@
var author, quote, sentence;
author = "Wittgenstein";
quote = "A picture is a fact. -- " + author;
sentence = "" + (22 / 7) + " is a decent approximation of π";
sentence = "" + (22 / 7) + " is a decent approximation of π";

View File

@@ -1,5 +1,7 @@
var city, forecast, temp, weatherReport, _ref;
weatherReport = function(location) {
return [location, 72, "Mostly Sunny"];
};
_ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];
_ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];

View File

@@ -1,15 +1,17 @@
var age, ages, child, yearsOld;
yearsOld = {
max: 10,
ida: 9,
tim: 11
};
ages = (function() {
var _results;
_results = [];
for (child in yearsOld) {
age = yearsOld[child];
_results.push(child + " is " + age);
_results.push("" + child + " is " + age);
}
return _results;
})();
})();

View File

@@ -1,4 +1,5 @@
var city, futurists, name, street, _ref, _ref2;
futurists = {
sculptor: "Umberto Boccioni",
painter: "Vladimir Burliuk",
@@ -7,4 +8,5 @@ futurists = {
address: ["Via Roma 42R", "Bellagio, Italy 22021"]
}
};
_ref = futurists.poet, name = _ref.name, _ref2 = _ref.address, street = _ref2[0], city = _ref2[1];
_ref = futurists.poet, name = _ref.name, (_ref2 = _ref.address, street = _ref2[0], city = _ref2[1]);

View File

@@ -1,10 +1,14 @@
var bitlist, kids, singers, song;
song = ["do", "re", "mi", "fa", "so"];
singers = {
Jagger: "Rock",
Elvis: "Roll"
};
bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0];
kids = {
brother: {
name: "Max",
@@ -14,4 +18,4 @@ kids = {
name: "Ida",
age: 9
}
};
};

View File

@@ -1,4 +1,6 @@
$('.account').attr({
"class": 'active'
});
log(object["class"]);
log(object["class"]);

View File

@@ -1,14 +1,18 @@
var cubes, list, math, num, number, opposite, race, square;
var __slice = Array.prototype.slice;
number = 42;
opposite = true;
if (opposite) {
number = -42;
}
if (opposite) number = -42;
square = function(x) {
return x * x;
};
list = [1, 2, 3, 4, 5];
math = {
root: Math.sqrt,
square: square,
@@ -16,14 +20,15 @@ math = {
return x * square(x);
}
};
race = function() {
var runners, winner;
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
return print(winner, runners);
};
if (typeof elvis != "undefined" && elvis !== null) {
alert("I knew it!");
}
if (typeof elvis !== "undefined" && elvis !== null) alert("I knew it!");
cubes = (function() {
var _i, _len, _results;
_results = [];
@@ -32,4 +37,4 @@ cubes = (function() {
_results.push(math.cube(num));
}
return _results;
})();
})();

View File

@@ -1,4 +1,7 @@
var theBait, theSwitch, _ref;
theBait = 1000;
theSwitch = 0;
_ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
_ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];

View File

@@ -1,4 +1,6 @@
var close, contents, open, tag, _i, _ref;
var __slice = Array.prototype.slice;
tag = "<impossible>";
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];

View File

@@ -1,3 +1,4 @@
String.prototype.dasherize = function() {
return this.replace(/_/g, "-");
};
};

View File

@@ -1,4 +1,5 @@
var countdown, num;
countdown = (function() {
var _results;
_results = [];
@@ -6,4 +7,4 @@ countdown = (function() {
_results.push(num);
}
return _results;
})();
})();

View File

@@ -1,8 +1,11 @@
var changeNumbers, inner, outer;
outer = 1;
changeNumbers = function() {
var inner;
inner = -1;
return outer = 10;
};
inner = changeNumbers();
inner = changeNumbers();

View File

@@ -1,4 +1,7 @@
var copy, middle, numbers;
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
copy = numbers.slice(0, numbers.length);
middle = copy.slice(3, 7);
middle = copy.slice(3, 7);

View File

@@ -1,2 +1,3 @@
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;

View File

@@ -1,6 +1,8 @@
var awardMedals, contenders, gold, rest, silver;
var __slice = Array.prototype.slice;
gold = silver = rest = "unknown";
awardMedals = function() {
var first, others, second;
first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
@@ -8,8 +10,13 @@ awardMedals = function() {
silver = second;
return rest = others;
};
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
awardMedals.apply(null, contenders);
alert("Gold: " + gold);
alert("Silver: " + silver);
alert("The Field: " + rest);
alert("The Field: " + rest);

View File

@@ -1,3 +1,5 @@
var numbers, _ref;
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
[].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
[].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;

View File

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

View File

@@ -1,3 +1,4 @@
switch (day) {
case "Mon":
go(work);
@@ -20,4 +21,4 @@ switch (day) {
break;
default:
go(work);
}
}

View File

@@ -1,3 +1,4 @@
try {
allHellBreaksLoose();
catsAndDogsLivingTogether();
@@ -5,4 +6,4 @@ try {
print(error);
} finally {
cleanUp();
}
}

View File

@@ -1,4 +1,5 @@
var lyrics, num;
if (this.studyingEconomics) {
while (supply > demand) {
buy();
@@ -7,12 +8,14 @@ if (this.studyingEconomics) {
sell();
}
}
num = 6;
lyrics = (function() {
var _results;
_results = [];
while (num -= 1) {
_results.push(num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
_results.push("" + num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
}
return _results;
})();
})();

File diff suppressed because it is too large Load Diff

9046
documentation/vendor/jquery-1.6.4.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ selection_sort = (list) ->
min = i
# Check the rest of the array to see if anything is smaller.
min = j if list[j] < list[min] for j in [i + 1...len]
min = k for v, k in list[i+1...] when v < list[min]
# Swap if a smaller item has been found.
[list[i], list[min]] = [list[min], list[i]] if i isnt min

View File

@@ -1,7 +0,0 @@
EXTRAS:
"extras/coffee-script.js" is a concatenated and compressed version of the
CoffeeScript compiler. To use it in the browser, include the script after any
inline script tags of type "text/coffeescript" on the page. It will compile
and evaluate all of the scripts in order.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
(function() {
var CoffeeScript, runScripts;
CoffeeScript = require('./coffee-script');
CoffeeScript.require = require;
CoffeeScript.eval = function(code, options) {
return eval(CoffeeScript.compile(code, options));
};
CoffeeScript.run = function(code, options) {
if (options == null) {
options = {};
}
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
};
if (typeof window == "undefined" || window === null) {
return;
}
CoffeeScript.load = function(url, options) {
var xhr;
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text/plain');
}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
return CoffeeScript.run(xhr.responseText, options);
}
};
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);
}
}
}
return null;
};
if (window.addEventListener) {
addEventListener('DOMContentLoaded', runScripts, false);
} else {
attachEvent('onload', runScripts);
}
}).call(this);

View File

@@ -1,82 +0,0 @@
(function() {
var Lexer, RESERVED, compile, fs, lexer, parser, path, _ref;
fs = require('fs');
path = require('path');
_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'));
return module._compile(content, filename);
};
} else if (require.registerExtension) {
require.registerExtension('.coffee', function(content) {
return compile(content);
});
}
exports.VERSION = '1.0.1';
exports.RESERVED = RESERVED;
exports.helpers = require('./helpers');
exports.compile = compile = function(code, options) {
if (options == null) {
options = {};
}
try {
return (parser.parse(lexer.tokenize(code))).compile(options);
} catch (err) {
if (options.filename) {
err.message = "In " + options.filename + ", " + err.message;
}
throw err;
}
};
exports.tokens = function(code, options) {
return lexer.tokenize(code, options);
};
exports.nodes = function(source, options) {
if (typeof source === 'string') {
return parser.parse(lexer.tokenize(source, options));
} else {
return parser.parse(source);
}
};
exports.run = function(code, options) {
var root;
root = module;
while (root.parent) {
root = root.parent;
}
root.filename = options.filename ? fs.realpathSync(options.filename) : '.';
if (root.moduleCache) {
root.moduleCache = {};
}
if (path.extname(root.filename) !== '.coffee' || require.extensions) {
return root._compile(compile(code, options), root.filename);
} else {
return root._compile(code, root.filename);
}
};
exports.eval = function(code, options) {
var __dirname, __filename;
__filename = module.filename = options.filename;
__dirname = path.dirname(__filename);
return eval(compile(code, options));
};
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];
return tag;
},
setInput: function(tokens) {
this.tokens = tokens;
return this.pos = 0;
},
upcomingInput: function() {
return "";
}
};
parser.yy = require('./nodes');
}).call(this);

View File

@@ -0,0 +1,74 @@
(function() {
var CoffeeScript, runScripts;
CoffeeScript = require('./coffee-script');
CoffeeScript.require = require;
CoffeeScript.eval = function(code, options) {
return eval(CoffeeScript.compile(code, options));
};
CoffeeScript.run = function(code, options) {
if (options == null) options = {};
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
};
if (typeof window === "undefined" || window === null) return;
CoffeeScript.load = function(url, callback) {
var xhr;
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
xhr.onreadystatechange = function() {
var _ref;
if (xhr.readyState === 4) {
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 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) {
addEventListener('DOMContentLoaded', runScripts, false);
} else {
attachEvent('onload', runScripts);
}
}).call(this);

69
lib/cake.js → lib/coffee-script/cake.js Executable file → Normal file
View File

@@ -1,14 +1,24 @@
(function() {
var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
var CoffeeScript, cakefileDirectory, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
fs = require('fs');
path = require('path');
helpers = require('./helpers');
optparse = require('./optparse');
CoffeeScript = require('./coffee-script');
tasks = {};
options = {};
switches = [];
oparse = null;
helpers.extend(global, {
task: function(name, description, action) {
var _ref;
@@ -25,36 +35,31 @@
return switches.push([letter, flag, description]);
},
invoke: function(name) {
if (!tasks[name]) {
missingTask(name);
}
if (!tasks[name]) missingTask(name);
return tasks[name].action(options);
}
});
exports.run = function() {
return path.exists('Cakefile', function(exists) {
var arg, args, _i, _len, _ref, _results;
if (!exists) {
throw new Error("Cakefile not found in " + (process.cwd()));
}
args = process.argv.slice(2);
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
filename: 'Cakefile'
});
oparse = new optparse.OptionParser(switches);
if (!args.length) {
return printTasks();
}
options = oparse.parse(args);
_ref = options.arguments;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
arg = _ref[_i];
_results.push(invoke(arg));
}
return _results;
var arg, args, _i, _len, _ref, _results;
global.__originalDirname = fs.realpathSync('.');
process.chdir(cakefileDirectory(__originalDirname));
args = process.argv.slice(2);
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
filename: 'Cakefile'
});
oparse = new optparse.OptionParser(switches);
if (!args.length) return printTasks();
options = oparse.parse(args);
_ref = options.arguments;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
arg = _ref[_i];
_results.push(invoke(arg));
}
return _results;
};
printTasks = function() {
var desc, name, spaces, task;
console.log('');
@@ -65,12 +70,20 @@
desc = task.description ? "# " + task.description : '';
console.log("cake " + name + spaces + " " + desc);
}
if (switches.length) {
return console.log(oparse.help());
}
if (switches.length) return console.log(oparse.help());
};
missingTask = function(task) {
console.log("No such task: \"" + task + "\"");
return process.exit(1);
};
cakefileDirectory = function(dir) {
var parent;
if (path.existsSync(path.join(dir, 'Cakefile'))) return dir;
parent = path.normalize(path.join(dir, '..'));
if (parent !== dir) return cakefileDirectory(parent);
throw new Error("Cakefile not found in " + (process.cwd()));
};
}).call(this);

View File

@@ -0,0 +1,148 @@
(function() {
var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref;
var __hasProp = Object.prototype.hasOwnProperty;
fs = require('fs');
path = require('path');
_ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
parser = require('./parser').parser;
vm = require('vm');
if (require.extensions) {
require.extensions['.coffee'] = function(module, filename) {
var content;
content = compile(fs.readFileSync(filename, 'utf8'), {
filename: filename
});
return module._compile(content, filename);
};
} else if (require.registerExtension) {
require.registerExtension('.coffee', function(content) {
return compile(content);
});
}
exports.VERSION = '1.1.3';
exports.RESERVED = RESERVED;
exports.helpers = require('./helpers');
exports.compile = compile = function(code, options) {
if (options == null) options = {};
try {
return (parser.parse(lexer.tokenize(code))).compile(options);
} catch (err) {
if (options.filename) {
err.message = "In " + options.filename + ", " + err.message;
}
throw err;
}
};
exports.tokens = function(code, options) {
return lexer.tokenize(code, options);
};
exports.nodes = function(source, options) {
if (typeof source === 'string') {
return parser.parse(lexer.tokenize(source, options));
} else {
return parser.parse(source);
}
};
exports.run = function(code, options) {
var mainModule;
mainModule = require.main;
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
mainModule.moduleCache && (mainModule.moduleCache = {});
mainModule.paths = require('module')._nodeModulePaths(path.dirname(options.filename));
if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
return mainModule._compile(compile(code, options), mainModule.filename);
} else {
return mainModule._compile(code, mainModule.filename);
}
};
exports.eval = function(code, options) {
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _require;
if (options == null) options = {};
if (!(code = code.trim())) return;
Script = vm.Script;
if (Script) {
if (options.sandbox != null) {
if (options.sandbox instanceof Script.createContext().constructor) {
sandbox = options.sandbox;
} else {
sandbox = Script.createContext();
_ref2 = options.sandbox;
for (k in _ref2) {
if (!__hasProp.call(_ref2, k)) continue;
v = _ref2[k];
sandbox[k] = v;
}
}
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
} else {
sandbox = global;
}
sandbox.__filename = options.filename || 'eval';
sandbox.__dirname = path.dirname(sandbox.__filename);
if (!(sandbox !== global || sandbox.module || sandbox.require)) {
Module = require('module');
sandbox.module = _module = new Module(options.modulename || 'eval');
sandbox.require = _require = function(path) {
return Module._load(path, _module, true);
};
_module.filename = sandbox.__filename;
_ref3 = Object.getOwnPropertyNames(require);
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
r = _ref3[_i];
if (r !== 'paths') _require[r] = require[r];
}
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
_require.resolve = function(request) {
return Module._resolveFilename(request, _module);
};
}
}
o = {};
for (k in options) {
if (!__hasProp.call(options, k)) continue;
v = options[k];
o[k] = v;
}
o.bare = true;
js = compile(code, o);
if (sandbox === global) {
return vm.runInThisContext(js);
} else {
return vm.runInContext(js, sandbox);
}
};
lexer = new Lexer;
parser.lexer = {
lex: function() {
var tag, _ref2;
_ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
return tag;
},
setInput: function(tokens) {
this.tokens = tokens;
return this.pos = 0;
},
upcomingInput: function() {
return "";
}
};
parser.yy = require('./nodes');
}).call(this);

View File

@@ -1,101 +1,133 @@
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compileScript, compileScripts, compileStdio, contents, exec, forkNode, fs, helpers, lint, loadRequires, optionParser, optparse, opts, parseOptions, path, printLine, printTokens, printWarn, sources, spawn, usage, version, watch, writeJs, _ref;
fs = require('fs');
path = require('path');
helpers = require('./helpers');
optparse = require('./optparse');
CoffeeScript = require('./coffee-script');
_ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
EventEmitter = require('events').EventEmitter;
helpers.extend(CoffeeScript, new EventEmitter);
printLine = function(line) {
return process.stdout.write(line + '\n');
};
printWarn = function(line) {
return process.binding('stdio').writeError(line + '\n');
return process.stderr.write(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']];
BANNER = 'Usage: coffee [options] path/to/script.coffee\n\nIf called without options, `coffee` will run your script.';
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
opts = {};
sources = [];
contents = [];
optionParser = null;
exports.run = function() {
parseOptions();
if (opts.nodejs) {
return forkNode();
}
if (opts.help) {
return usage();
}
if (opts.version) {
return version();
}
if (opts.require) {
loadRequires();
}
if (opts.interactive) {
return require('./repl');
}
if (opts.stdio) {
return compileStdio();
}
if (opts.eval) {
return compileScript(null, sources[0]);
}
if (!sources.length) {
return require('./repl');
}
if (opts.run) {
opts.literals = sources.splice(1).concat(opts.literals);
}
process.ARGV = process.argv = process.argv.slice(0, 2).concat(opts.literals);
if (opts.nodejs) return forkNode();
if (opts.help) return usage();
if (opts.version) return version();
if (opts.require) loadRequires();
if (opts.interactive) return require('./repl');
if (opts.stdio) return compileStdio();
if (opts.eval) return compileScript(null, sources[0]);
if (!sources.length) return require('./repl');
if (opts.run) opts.literals = sources.splice(1).concat(opts.literals);
process.argv = process.argv.slice(0, 2).concat(opts.literals);
process.argv[0] = 'coffee';
process.execPath = require.main.filename;
return compileScripts();
};
compileScripts = function() {
var base, compile, source, _i, _len, _results;
_results = [];
var base, compile, remaining_files, source, trackCompleteFiles, trackUnprocessedFiles, unprocessed, _i, _j, _len, _len2, _results;
unprocessed = [];
remaining_files = function() {
var total, x, _i, _len;
total = 0;
for (_i = 0, _len = unprocessed.length; _i < _len; _i++) {
x = unprocessed[_i];
total += x;
}
return total;
};
trackUnprocessedFiles = function(sourceIndex, fileCount) {
var _ref2;
if ((_ref2 = unprocessed[sourceIndex]) == null) unprocessed[sourceIndex] = 0;
return unprocessed[sourceIndex] += fileCount;
};
trackCompleteFiles = function(sourceIndex, fileCount) {
unprocessed[sourceIndex] -= fileCount;
if (opts.join) {
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
return compileJoin();
}
}
};
for (_i = 0, _len = sources.length; _i < _len; _i++) {
source = sources[_i];
trackUnprocessedFiles(sources.indexOf(source), 1);
}
_results = [];
for (_j = 0, _len2 = sources.length; _j < _len2; _j++) {
source = sources[_j];
base = path.join(source);
compile = function(source, topLevel) {
compile = function(source, sourceIndex, topLevel) {
return path.exists(source, function(exists) {
if (topLevel && !exists) {
throw new Error("File not found: " + source);
if (topLevel && !exists && source.slice(-7) !== '.coffee') {
return compile("" + source + ".coffee", sourceIndex, topLevel);
}
if (topLevel && !exists) 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, _k, _len3;
if (err) throw err;
trackUnprocessedFiles(sourceIndex, files.length);
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
file = files[_k];
compile(path.join(source, file), sourceIndex);
}
return _results;
return trackCompleteFiles(sourceIndex, 1);
});
} else if (topLevel || path.extname(source) === '.coffee') {
fs.readFile(source, function(err, code) {
if (err) throw err;
if (opts.join) {
contents[sources.indexOf(source)] = code.toString();
if (helpers.compact(contents).length === sources.length) {
return compileJoin();
}
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
} else {
return compileScript(source, code.toString(), base);
compileScript(source, code.toString(), base);
}
return trackCompleteFiles(sourceIndex, 1);
});
if (opts.watch && !opts.join) {
return watch(source, base);
}
if (opts.watch && !opts.join) return watch(source, base);
} else {
return trackCompleteFiles(sourceIndex, 1);
}
});
});
};
_results.push(compile(source, true));
_results.push(compile(source, sources.indexOf(source), true));
}
return _results;
};
compileScript = function(file, input, base) {
var o, options, t, task;
o = opts;
@@ -126,61 +158,64 @@
}
} catch (err) {
CoffeeScript.emit('failure', err, task);
if (CoffeeScript.listeners('failure').length) {
return;
}
if (o.watch) {
return printLine(err.message);
}
printWarn(err.stack);
if (CoffeeScript.listeners('failure').length) return;
if (o.watch) return printLine(err.message);
printWarn(err instanceof Error && err.stack || ("ERROR: " + err));
return process.exit(1);
}
};
compileStdio = function() {
var code, stdin;
code = '';
stdin = process.openStdin();
stdin.on('data', function(buffer) {
if (buffer) {
return code += buffer.toString();
}
if (buffer) return code += buffer.toString();
});
return stdin.on('end', function() {
return compileScript(null, code);
});
};
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;
};
watch = function(source, base) {
return fs.watchFile(source, {
persistent: true,
interval: 500
}, function(curr, prev) {
if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) {
return;
}
return fs.readFile(source, function(err, code) {
if (err) {
throw err;
return fs.stat(source, function(err, prevStats) {
if (err) throw err;
return fs.watch(source, function(event) {
if (event === 'change') {
return fs.stat(source, function(err, stats) {
if (err) throw err;
if (stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
return;
}
prevStats = stats;
return fs.readFile(source, function(err, code) {
if (err) throw err;
return compileScript(source, code.toString(), base);
});
});
}
return compileScript(source, code.toString(), base);
});
});
};
writeJs = function(source, js, base) {
var baseDir, compile, dir, filename, jsPath, srcDir;
filename = path.basename(source, path.extname(source)) + '.js';
@@ -189,14 +224,12 @@
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
jsPath = path.join(dir, filename);
compile = function() {
if (js.length <= 0) {
js = ' ';
}
if (js.length <= 0) js = ' ';
return fs.writeFile(jsPath, js, function(err) {
if (err) {
return printLine(err.message);
} else if (opts.compile && opts.watch) {
return console.log("" + ((new Date).toTimeString()) + " - compiled " + source);
return console.log("" + ((new Date).toLocaleTimeString()) + " - compiled " + source);
}
});
};
@@ -208,32 +241,35 @@
}
});
};
lint = function(file, js) {
var conf, jsl, printIt;
printIt = function(buffer) {
return printLine(file + ':\t' + buffer.toString().trim());
};
conf = __dirname + '/../extras/jsl.conf';
conf = __dirname + '/../../extras/jsl.conf';
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
jsl.stdout.on('data', printIt);
jsl.stderr.on('data', printIt);
jsl.stdin.write(js);
return jsl.stdin.end();
};
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;
})();
return printLine(strings.join(' '));
};
parseOptions = function() {
var o;
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
@@ -243,12 +279,14 @@
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
return sources = o.arguments;
};
compileOptions = function(filename) {
return {
filename: filename,
bare: opts.bare
};
};
forkNode = function() {
var args, nodeArgs;
nodeArgs = opts.nodejs.split(/\s+/);
@@ -260,10 +298,13 @@
customFds: [0, 1, 2]
});
};
usage = function() {
return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
};
version = function() {
return printLine("CoffeeScript version " + CoffeeScript.VERSION);
};
}).call(this);

View File

@@ -1,18 +1,20 @@
(function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
Parser = require('jison').Parser;
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
o = function(patternString, action, options) {
var match;
patternString = patternString.replace(/\s{2,}/g, ' ');
if (!action) {
return [patternString, '$$ = $1;', options];
}
if (!action) return [patternString, '$$ = $1;', options];
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
return [patternString, "$$ = " + action + ";", options];
};
grammar = {
Root: [
o('', function() {
@@ -60,9 +62,7 @@
}), o('BOOL', function() {
var val;
val = new Literal($1);
if ($1 === 'undefined') {
val.isUndefined = true;
}
if ($1 === 'undefined') val.isUndefined = true;
return val;
})
],
@@ -139,7 +139,7 @@
o('Identifier', function() {
return new Value($1);
}), o('Value Accessor', function() {
return $1.push($2);
return $1.add($2);
}), o('Invocation Accessor', function() {
return new Value($1, [$2]);
}), o('ThisProperty')
@@ -166,24 +166,25 @@
}), o('?. Identifier', function() {
return new Access($2, 'soak');
}), o(':: Identifier', function() {
return new Access($2, 'proto');
return [new Access(new Literal('prototype')), new Access($2)];
}), 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
});
}), o('INDEX_PROTO Index', function() {
return extend($2, {
proto: true
});
})
],
IndexValue: [
o('Expression', function() {
return new Index($1);
}), o('Slice', function() {
return new Slice($1);
})
],
Object: [
@@ -209,17 +210,17 @@
return new Class;
}), o('CLASS Block', function() {
return new Class(null, null, $2);
}), o('CLASS EXTENDS Value', function() {
}), o('CLASS EXTENDS Expression', function() {
return new Class(null, $3);
}), o('CLASS EXTENDS Value Block', function() {
}), o('CLASS EXTENDS Expression Block', function() {
return new Class(null, $3, $4);
}), o('CLASS SimpleAssignable', function() {
return new Class($2);
}), o('CLASS SimpleAssignable Block', function() {
return new Class($2, null, $3);
}), o('CLASS SimpleAssignable EXTENDS Value', function() {
}), o('CLASS SimpleAssignable EXTENDS Expression', function() {
return new Class($2, $4);
}), o('CLASS SimpleAssignable EXTENDS Value Block', function() {
}), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
return new Class($2, $4, $5);
})
],
@@ -280,12 +281,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: [
@@ -553,8 +554,11 @@
})
]
};
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
tokens = [];
for (name in grammar) {
alternatives = grammar[name];
grammar[name] = (function() {
@@ -565,22 +569,20 @@
_ref = alt[0].split(' ');
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
token = _ref[_j];
if (!grammar[token]) {
tokens.push(token);
}
}
if (name === 'Root') {
alt[1] = "return " + alt[1];
if (!grammar[token]) tokens.push(token);
}
if (name === 'Root') alt[1] = "return " + alt[1];
_results.push(alt);
}
return _results;
})();
}
exports.parser = new Parser({
tokens: tokens.join(' '),
bnf: grammar,
operators: operators.reverse(),
startSymbol: 'Root'
});
}).call(this);

View File

@@ -1,38 +1,40 @@
(function() {
var extend, flatten;
exports.starts = function(string, literal, start) {
return literal === string.substr(start, literal.length);
};
exports.ends = function(string, literal, back) {
var len;
len = literal.length;
return literal === string.substr(string.length - len - (back || 0), len);
};
exports.compact = function(array) {
var item, _i, _len, _results;
_results = [];
for (_i = 0, _len = array.length; _i < _len; _i++) {
item = array[_i];
if (item) {
_results.push(item);
}
if (item) _results.push(item);
}
return _results;
};
exports.count = function(string, substr) {
var num, pos;
num = pos = 0;
if (!substr.length) {
return 1 / 0;
}
if (!substr.length) return 1 / 0;
while (pos = 1 + string.indexOf(substr, pos)) {
num++;
}
return num;
};
exports.merge = function(options, overrides) {
return extend(extend({}, options), overrides);
};
extend = exports.extend = function(object, properties) {
var key, val;
for (key in properties) {
@@ -41,6 +43,7 @@
}
return object;
};
exports.flatten = flatten = function(array) {
var element, flattened, _i, _len;
flattened = [];
@@ -54,13 +57,16 @@
}
return flattened;
};
exports.del = function(obj, key) {
var val;
val = obj[key];
delete obj[key];
return val;
};
exports.last = function(array, back) {
return array[array.length - (back || 0) - 1];
};
}).call(this);

View File

@@ -1,8 +1,10 @@
(function() {
var key, val, _ref;
_ref = require('./coffee-script');
for (key in _ref) {
val = _ref[key];
exports[key] = val;
}
}).call(this);

View File

@@ -1,23 +1,19 @@
(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 __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
}
return -1;
};
Rewriter = require('./rewriter').Rewriter;
_ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref2;
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; };
_ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
_ref2 = require('./helpers'), count = _ref2.count, starts = _ref2.starts, compact = _ref2.compact, last = _ref2.last;
exports.Lexer = Lexer = (function() {
function Lexer() {}
Lexer.prototype.tokenize = function(code, opts) {
var i;
if (opts == null) {
opts = {};
}
if (WHITESPACE.test(code)) {
code = "\n" + code;
}
var i, tag;
if (opts == null) opts = {};
if (WHITESPACE.test(code)) code = "\n" + code;
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
this.code = code;
this.line = opts.line || 0;
@@ -25,32 +21,31 @@
this.indebt = 0;
this.outdebt = 0;
this.indents = [];
this.ends = [];
this.tokens = [];
i = 0;
while (this.chunk = code.slice(i)) {
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
}
this.closeIndentation();
if (opts.rewrite === false) {
return this.tokens;
}
if (tag = this.ends.pop()) this.error("missing " + tag);
if (opts.rewrite === false) return this.tokens;
return (new Rewriter).rewrite(this.tokens);
};
Lexer.prototype.identifierToken = function() {
var colon, forcedIdentifier, id, input, match, prev, tag, _ref, _ref2;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return 0;
}
var colon, forcedIdentifier, id, input, match, prev, tag, _ref3, _ref4;
if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
input = match[0], id = match[1], colon = match[2];
if (id === 'own' && this.tag() === 'FOR') {
this.token('OWN', id);
return id.length;
}
forcedIdentifier = colon || (prev = last(this.tokens)) && !prev.spaced && ((_ref = prev[0]) === '.' || _ref === '?.' || _ref === '@' || _ref === '::');
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref3 = prev[0]) === '.' || _ref3 === '?.' || _ref3 === '::') || !prev.spaced && prev[0] === '@');
tag = 'IDENTIFIER';
if (__indexOf.call(JS_KEYWORDS, id) >= 0 || !forcedIdentifier && __indexOf.call(COFFEE_KEYWORDS, id) >= 0) {
if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
tag = id.toUpperCase();
if (tag === 'WHEN' && (_ref2 = this.tag(), __indexOf.call(LINE_BREAK, _ref2) >= 0)) {
if (tag === 'WHEN' && (_ref4 = this.tag(), __indexOf.call(LINE_BREAK, _ref4) >= 0)) {
tag = 'LEADING_WHEN';
} else if (tag === 'FOR') {
this.seenFor = true;
@@ -71,19 +66,17 @@
}
}
}
if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
if (__indexOf.call(['eval', 'arguments'].concat(JS_FORBIDDEN), id) >= 0) {
if (forcedIdentifier) {
tag = 'IDENTIFIER';
id = new String(id);
id.reserved = true;
} else if (__indexOf.call(RESERVED, id) >= 0) {
this.identifierError(id);
this.error("reserved word \"" + word + "\"");
}
}
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) {
case '!':
@@ -109,33 +102,31 @@
})();
}
this.token(tag, id);
if (colon) {
this.token(':', ':');
}
if (colon) this.token(':', ':');
return input.length;
};
Lexer.prototype.numberToken = function() {
var match, number;
if (!(match = NUMBER.exec(this.chunk))) {
return 0;
}
var binaryLiteral, lexedLength, match, number;
if (!(match = NUMBER.exec(this.chunk))) return 0;
number = match[0];
lexedLength = number.length;
if (binaryLiteral = /0b([01]+)/.exec(number)) {
number = (parseInt(binaryLiteral[1], 2)).toString();
}
this.token('NUMBER', number);
return number.length;
return lexedLength;
};
Lexer.prototype.stringToken = function() {
var match, string;
switch (this.chunk.charAt(0)) {
case "'":
if (!(match = SIMPLESTR.exec(this.chunk))) {
return 0;
}
if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
break;
case '"':
if (!(string = this.balancedString(this.chunk, '"'))) {
return 0;
}
if (!(string = this.balancedString(this.chunk, '"'))) return 0;
if (0 < string.indexOf('#{', 1)) {
this.interpolateString(string.slice(1, -1));
} else {
@@ -148,11 +139,10 @@
this.line += count(string, '\n');
return string.length;
};
Lexer.prototype.heredocToken = function() {
var doc, heredoc, match, quote;
if (!(match = HEREDOC.exec(this.chunk))) {
return 0;
}
if (!(match = HEREDOC.exec(this.chunk))) return 0;
heredoc = match[0];
quote = heredoc.charAt(0);
doc = this.sanitizeHeredoc(match[2], {
@@ -169,13 +159,11 @@
this.line += count(heredoc, '\n');
return heredoc.length;
};
Lexer.prototype.commentToken = function() {
var comment, here, match;
if (!(match = this.chunk.match(COMMENT))) {
return 0;
}
if (!(match = this.chunk.match(COMMENT))) return 0;
comment = match[0], here = match[1];
this.line += count(comment, '\n');
if (here) {
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
herecomment: true,
@@ -183,8 +171,10 @@
}));
this.token('TERMINATOR', '\n');
}
this.line += count(comment, '\n');
return comment.length;
};
Lexer.prototype.jsToken = function() {
var match, script;
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
@@ -193,70 +183,73 @@
this.token('JS', (script = match[0]).slice(1, -1));
return script.length;
};
Lexer.prototype.regexToken = function() {
var match, prev, regex, _ref;
if (this.chunk.charAt(0) !== '/') {
return 0;
}
var flags, length, match, prev, regex, _ref3, _ref4;
if (this.chunk.charAt(0) !== '/') return 0;
if (match = HEREGEX.exec(this.chunk)) {
return this.heregexToken(match);
length = this.heregexToken(match);
this.line += count(match[0], '\n');
return length;
}
prev = last(this.tokens);
if (prev && (_ref = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref) >= 0)) {
if (prev && (_ref3 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref3) >= 0)) {
return 0;
}
if (!(match = REGEX.exec(this.chunk))) {
return 0;
if (!(match = REGEX.exec(this.chunk))) return 0;
_ref4 = match, match = _ref4[0], regex = _ref4[1], flags = _ref4[2];
if (regex.slice(0, 2) === '/*') {
this.error('regular expressions cannot begin with `*`');
}
regex = match[0];
this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
return regex.length;
if (regex === '//') regex = '/(?:)/';
this.token('REGEX', "" + regex + flags);
return match.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, _ref3, _ref4, _ref5, _ref6;
heregex = match[0], body = match[1], flags = match[2];
if (0 > body.indexOf('#{')) {
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
if (re.match(/^\*/)) {
this.error('regular expressions cannot begin with `*`');
}
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
return heregex.length;
}
this.token('IDENTIFIER', 'RegExp');
this.tokens.push(['CALL_START', '(']);
tokens = [];
_ref = this.interpolateString(body, {
_ref3 = 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 = _ref3.length; _i < _len; _i++) {
_ref4 = _ref3[_i], tag = _ref4[0], value = _ref4[1];
if (tag === 'TOKENS') {
tokens.push.apply(tokens, value);
} else {
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
continue;
}
if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
value = value.replace(/\\/g, '\\\\');
tokens.push(['STRING', this.makeString(value, '"', true)]);
}
tokens.push(['+', '+']);
}
tokens.pop();
if (((_ref3 = tokens[0]) != null ? _ref3[0] : void 0) !== 'STRING') {
if (((_ref5 = tokens[0]) != null ? _ref5[0] : void 0) !== 'STRING') {
this.tokens.push(['STRING', '""'], ['+', '+']);
}
(_ref4 = this.tokens).push.apply(_ref4, tokens);
if (flags) {
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
}
(_ref6 = this.tokens).push.apply(_ref6, tokens);
if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
this.token(')', ')');
return heregex.length;
};
Lexer.prototype.lineToken = function() {
var diff, indent, match, noNewlines, prev, size;
if (!(match = MULTI_DENT.exec(this.chunk))) {
return 0;
}
if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
indent = match[0];
this.line += count(indent, '\n');
this.seenFor = false;
prev = last(this.tokens, 1);
size = indent.length - 1 - indent.lastIndexOf('\n');
noNewlines = this.unfinished();
@@ -277,6 +270,7 @@
diff = size - this.indent + this.outdebt;
this.token('INDENT', diff);
this.indents.push(diff);
this.ends.push('OUTDENT');
this.outdebt = this.indebt = 0;
} else {
this.indebt = 0;
@@ -285,7 +279,8 @@
this.indent = size;
return indent.length;
};
Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
var dent, len;
while (moveOut > 0) {
len = this.indents.length - 1;
@@ -301,67 +296,69 @@
dent = this.indents.pop() - this.outdebt;
moveOut -= dent;
this.outdebt = 0;
this.pair('OUTDENT');
this.token('OUTDENT', dent);
}
}
if (dent) {
this.outdebt -= moveOut;
if (dent) this.outdebt -= moveOut;
while (this.value() === ';') {
this.tokens.pop();
}
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
this.token('TERMINATOR', '\n');
}
return this;
};
Lexer.prototype.whitespaceToken = function() {
var match, nline, prev;
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
return 0;
}
prev = last(this.tokens);
if (prev) {
prev[match ? 'spaced' : 'newLine'] = true;
}
if (prev) prev[match ? 'spaced' : 'newLine'] = true;
if (match) {
return match[0].length;
} else {
return 0;
}
};
Lexer.prototype.newlineToken = function() {
if (this.tag() !== 'TERMINATOR') {
this.token('TERMINATOR', '\n');
}
return this;
};
Lexer.prototype.suppressNewlines = function() {
if (this.value() === '\\') {
while (this.value() === ';') {
this.tokens.pop();
}
if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
return this;
};
Lexer.prototype.suppressNewlines = function() {
if (this.value() === '\\') this.tokens.pop();
return this;
};
Lexer.prototype.literalToken = function() {
var match, prev, tag, value, _ref, _ref2, _ref3, _ref4;
var match, prev, tag, value, _ref3, _ref4, _ref5, _ref6;
if (match = OPERATOR.exec(this.chunk)) {
value = match[0];
if (CODE.test(value)) {
this.tagParameters();
}
if (CODE.test(value)) this.tagParameters();
} else {
value = this.chunk.charAt(0);
}
tag = value;
prev = last(this.tokens);
if (value === '=' && prev) {
if (!prev[1].reserved && (_ref = prev[1], __indexOf.call(JS_FORBIDDEN, _ref) >= 0)) {
this.assignmentError();
if (!prev[1].reserved && (_ref3 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref3) >= 0)) {
this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
}
if ((_ref2 = prev[1]) === '||' || _ref2 === '&&') {
if ((_ref4 = prev[1]) === '||' || _ref4 === '&&') {
prev[0] = 'COMPOUND_ASSIGN';
prev[1] += '=';
return value.length;
}
}
if (value === ';') {
this.seenFor = false;
tag = 'TERMINATOR';
} else if (__indexOf.call(MATH, value) >= 0) {
tag = 'MATH';
@@ -376,52 +373,56 @@
} 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 (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
if (value === '(' && (_ref5 = prev[0], __indexOf.call(CALLABLE, _ref5) >= 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 === '[' && (_ref6 = prev[0], __indexOf.call(INDEXABLE, _ref6) >= 0)) {
tag = 'INDEX_START';
switch (prev[0]) {
case '?':
prev[0] = 'INDEX_SOAK';
break;
case '::':
prev[0] = 'INDEX_PROTO';
}
}
}
switch (value) {
case '(':
case '{':
case '[':
this.ends.push(INVERSES[value]);
break;
case ')':
case '}':
case ']':
this.pair(value);
}
this.token(tag, value);
return value.length;
};
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
var attempt, herecomment, indent, match, _ref;
var attempt, herecomment, indent, match, _ref3;
indent = options.indent, herecomment = options.herecomment;
if (herecomment && 0 > doc.indexOf('\n')) {
return doc;
}
if (!herecomment) {
if (herecomment) {
if (HEREDOC_ILLEGAL.test(doc)) {
this.error("block comment cannot contain \"*/\", starting");
}
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 < (_ref3 = attempt.length) && _ref3 < indent.length)) {
indent = attempt;
}
}
}
if (indent) {
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
}
if (!herecomment) {
doc = doc.replace(/^\n/, '');
}
if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
if (!herecomment) doc = doc.replace(/^\n/, '');
return doc;
};
Lexer.prototype.tagParameters = function() {
var i, stack, tok, tokens;
if (this.tag() !== ')') {
return this;
}
if (this.tag() !== ')') return this;
stack = [];
tokens = this.tokens;
i = tokens.length;
@@ -435,41 +436,39 @@
case 'CALL_START':
if (stack.length) {
stack.pop();
} else {
} else if (tok[0] === '(') {
tok[0] = 'PARAM_START';
return this;
} else {
return this;
}
}
}
return this;
};
Lexer.prototype.closeIndentation = function() {
return this.outdentToken(this.indent);
};
Lexer.prototype.identifierError = function(word) {
throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
};
Lexer.prototype.assignmentError = function() {
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, match, prev, stack, _ref3;
stack = [end];
for (i = 1, _ref = str.length; (1 <= _ref ? i < _ref : i > _ref); (1 <= _ref ? i += 1 : i -= 1)) {
for (i = 1, _ref3 = str.length; 1 <= _ref3 ? i < _ref3 : i > _ref3; 1 <= _ref3 ? i++ : i--) {
switch (letter = str.charAt(i)) {
case '\\':
i++;
continue;
case end:
stack.pop();
if (!stack.length) {
return str.slice(0, i + 1);
}
if (!stack.length) return str.slice(0, i + 1);
end = stack[stack.length - 1];
continue;
}
if (end === '}' && (letter === '"' || letter === "'")) {
stack.push(end = letter);
} else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
i += match[0].length - 1;
} else if (end === '}' && letter === '{') {
stack.push(end = '}');
} else if (end === '"' && prev === '#' && letter === '{') {
@@ -477,13 +476,12 @@
}
prev = letter;
}
throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
return this.error("missing " + (stack.pop()) + ", starting");
};
Lexer.prototype.interpolateString = function(str, options) {
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref, _ref2, _ref3;
if (options == null) {
options = {};
}
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref3, _ref4, _ref5;
if (options == null) options = {};
heredoc = options.heredoc, regex = options.regex;
tokens = [];
pi = 0;
@@ -496,9 +494,7 @@
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
continue;
}
if (pi < i) {
tokens.push(['NEOSTRING', str.slice(pi, i)]);
}
if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
inner = expr.slice(1, -1);
if (inner.length) {
nested = new Lexer().tokenize(inner, {
@@ -506,7 +502,7 @@
rewrite: false
});
nested.pop();
if (((_ref = nested[0]) != null ? _ref[0] : void 0) === 'TERMINATOR') {
if (((_ref3 = nested[0]) != null ? _ref3[0] : void 0) === 'TERMINATOR') {
nested.shift();
}
if (len = nested.length) {
@@ -520,59 +516,60 @@
i += expr.length;
pi = i + 1;
}
if ((i > pi && pi < str.length)) {
tokens.push(['NEOSTRING', str.slice(pi)]);
}
if (regex) {
return tokens;
}
if (!tokens.length) {
return this.token('STRING', '""');
}
if (tokens[0][0] !== 'NEOSTRING') {
tokens.unshift(['', '']);
}
if (interpolated = tokens.length > 1) {
this.token('(', '(');
}
if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
if (regex) return tokens;
if (!tokens.length) return this.token('STRING', '""');
if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
if (interpolated = tokens.length > 1) this.token('(', '(');
for (i = 0, _len = tokens.length; i < _len; i++) {
_ref2 = tokens[i], tag = _ref2[0], value = _ref2[1];
if (i) {
this.token('+', '+');
}
_ref4 = tokens[i], tag = _ref4[0], value = _ref4[1];
if (i) this.token('+', '+');
if (tag === 'TOKENS') {
(_ref3 = this.tokens).push.apply(_ref3, value);
(_ref5 = this.tokens).push.apply(_ref5, value);
} else {
this.token('STRING', this.makeString(value, '"', heredoc));
}
}
if (interpolated) {
this.token(')', ')');
}
if (interpolated) this.token(')', ')');
return tokens;
};
Lexer.prototype.pair = function(tag) {
var size, wanted;
if (tag !== (wanted = last(this.ends))) {
if ('OUTDENT' !== wanted) this.error("unmatched " + tag);
this.indent -= size = last(this.indents);
this.outdentToken(size, true);
return this.pair(tag);
}
return this.ends.pop();
};
Lexer.prototype.token = function(tag, value) {
return this.tokens.push([tag, value, this.line]);
};
Lexer.prototype.tag = function(index, tag) {
var tok;
return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
};
Lexer.prototype.value = function(index, val) {
var tok;
return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
};
Lexer.prototype.unfinished = function() {
var prev, value;
return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
var _ref3;
return LINE_CONTINUER.test(this.chunk) || ((_ref3 = this.tag()) === '\\' || _ref3 === '.' || _ref3 === '?.' || _ref3 === 'UNARY' || _ref3 === 'MATH' || _ref3 === '+' || _ref3 === '-' || _ref3 === 'SHIFT' || _ref3 === 'RELATION' || _ref3 === 'COMPARE' || _ref3 === 'LOGIC' || _ref3 === 'COMPOUND_ASSIGN' || _ref3 === 'THROW' || _ref3 === 'EXTENDS');
};
Lexer.prototype.escapeLines = function(str, heredoc) {
return str.replace(MULTILINER, heredoc ? '\\n' : '');
};
Lexer.prototype.makeString = function(body, quote, heredoc) {
if (!body) {
return quote + quote;
}
if (!body) return quote + quote;
body = body.replace(/\\([\s\S])/g, function(match, contents) {
if (contents === '\n' || contents === quote) {
return contents;
@@ -583,11 +580,20 @@
body = body.replace(RegExp("" + quote, "g"), '\\$&');
return quote + this.escapeLines(body, heredoc) + quote;
};
Lexer.prototype.error = function(message) {
throw SyntaxError("" + message + " on line " + (this.line + 1));
};
return Lexer;
})();
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,42 +603,85 @@
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);
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
NUMBER = /^0x[\da-f]+|^(?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i;
NUMBER = /^0x[\da-f]+|^0b[01]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
WHITESPACE = /^[^\n\S]+/;
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
CODE = /^[-=]>/;
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;
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
LINE_CONTINUER = /^\s*(?:,|\??\.(?!\.)|::)/;
HEREDOC_ILLEGAL = /\*\//;
LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
TRAILING_SPACES = /\s+$/;
NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
LOGIC = ['&&', '||', '&', '|', '^'];
SHIFT = ['<<', '>>', '>>>'];
COMPARE = ['==', '!=', '<', '>', '<=', '>='];
MATH = ['*', '/', '%'];
RELATION = ['IN', 'OF', 'INSTANCEOF'];
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
}).call(this);

File diff suppressed because it is too large Load Diff

35
lib/optparse.js → lib/coffee-script/optparse.js Executable file → Normal file
View File

@@ -1,21 +1,27 @@
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
exports.OptionParser = OptionParser = (function() {
function OptionParser(rules, banner) {
this.banner = banner;
this.rules = buildRules(rules);
}
OptionParser.prototype.parse = function(args) {
var arg, i, isOption, matchedRule, options, rule, value, _i, _len, _len2, _ref;
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, value, _i, _len, _len2, _ref;
options = {
arguments: [],
literals: []
};
originalArgs = args;
args = normalizeArguments(args);
for (i = 0, _len = args.length; i < _len; i++) {
arg = args[i];
if (arg === '--') {
options.literals = args.slice(i + 1);
pos = originalArgs.indexOf('--');
options.arguments = [originalArgs[1 + pos]];
options.literals = originalArgs.slice(2 + pos);
break;
}
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
@@ -34,18 +40,17 @@
throw new Error("unrecognized option: " + arg);
}
if (!isOption) {
options.arguments = args.slice(i);
options.arguments = originalArgs.slice(originalArgs.indexOf(arg));
break;
}
}
return options;
};
OptionParser.prototype.help = function() {
var letPart, lines, rule, spaces, _i, _len, _ref;
lines = [];
if (this.banner) {
lines.unshift("" + this.banner + "\n");
}
if (this.banner) lines.unshift("" + this.banner + "\n");
_ref = this.rules;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
rule = _ref[_i];
@@ -56,29 +61,33 @@
}
return "\n" + (lines.join('\n')) + "\n";
};
return OptionParser;
})();
LONG_FLAG = /^(--\w[\w\-]+)/;
SHORT_FLAG = /^(-\w)/;
MULTI_FLAG = /^-(\w{2,})/;
OPTIONAL = /\[(\w+(\*?))\]/;
buildRules = function(rules) {
var tuple, _i, _len, _results;
_results = [];
for (_i = 0, _len = rules.length; _i < _len; _i++) {
tuple = rules[_i];
if (tuple.length < 3) {
tuple.unshift(null);
}
if (tuple.length < 3) tuple.unshift(null);
_results.push(buildRule.apply(null, tuple));
}
return _results;
};
buildRule = function(shortFlag, longFlag, description, options) {
var match;
if (options == null) {
options = {};
}
if (options == null) options = {};
match = longFlag.match(OPTIONAL);
longFlag = longFlag.match(LONG_FLAG)[1];
return {
@@ -90,6 +99,7 @@
isList: !!(match && match[2])
};
};
normalizeArguments = function(args) {
var arg, l, match, result, _i, _j, _len, _len2, _ref;
args = args.slice(0);
@@ -108,4 +118,5 @@
}
return result;
};
}).call(this);

670
lib/coffee-script/parser.js Executable file

File diff suppressed because one or more lines are too long

149
lib/coffee-script/repl.js Normal file
View File

@@ -0,0 +1,149 @@
(function() {
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, readline, repl, run, stdin, stdout;
CoffeeScript = require('./coffee-script');
readline = require('readline');
inspect = require('util').inspect;
Script = require('vm').Script;
Module = require('module');
REPL_PROMPT = 'coffee> ';
REPL_PROMPT_CONTINUATION = '......> ';
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');
};
backlog = '';
run = function(buffer) {
var code, returnValue, _;
if (!buffer.toString().trim() && !backlog) {
repl.prompt();
return;
}
code = backlog += buffer;
if (code[code.length - 1] === '\\') {
backlog = "" + backlog.slice(0, -1) + "\n";
repl.setPrompt(REPL_PROMPT_CONTINUATION);
repl.prompt();
return;
}
repl.setPrompt(REPL_PROMPT);
backlog = '';
try {
_ = global._;
returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
filename: 'repl',
modulename: 'repl'
});
if (returnValue === void 0) global._ = _;
process.stdout.write(inspect(returnValue, 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;
}
completions = getCompletions(prefix, Object.getOwnPropertyNames(val));
return [completions, prefix];
}
};
completeVariable = function(text) {
var completions, free, keywords, possibilities, r, vars, _ref;
free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0;
if (free != null) {
vars = Script.runInThisContext('Object.getOwnPropertyNames(this)');
keywords = (function() {
var _i, _len, _ref2, _results;
_ref2 = CoffeeScript.RESERVED;
_results = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
r = _ref2[_i];
if (r.slice(0, 2) !== '__') _results.push(r);
}
return _results;
})();
possibilities = vars.concat(keywords);
completions = getCompletions(free, possibilities);
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;
};
process.on('uncaughtException', error);
if (readline.createInterface.length < 3) {
repl = readline.createInterface(stdin, autocomplete);
stdin.on('data', function(buffer) {
return repl.write(buffer);
});
} else {
repl = readline.createInterface(stdin, stdout, autocomplete);
}
repl.on('attemptClose', function() {
if (backlog) {
backlog = '';
process.stdout.write('\n');
repl.setPrompt(REPL_PROMPT);
return repl.prompt();
} else {
return repl.close();
}
});
repl.on('close', function() {
process.stdout.write('\n');
return stdin.destroy();
});
repl.on('line', run);
repl.setPrompt(REPL_PROMPT);
repl.prompt();
}).call(this);

View File

@@ -1,13 +1,11 @@
(function() {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
}
return -1;
}, __slice = Array.prototype.slice;
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; }, __slice = Array.prototype.slice;
exports.Rewriter = (function() {
function Rewriter() {}
Rewriter.prototype.rewrite = function(tokens) {
this.tokens = tokens;
this.removeLeadingNewlines();
@@ -18,10 +16,9 @@
this.tagPostfixConditionals();
this.addImplicitBraces();
this.addImplicitParentheses();
this.ensureBalance(BALANCED_PAIRS);
this.rewriteClosingParens();
return this.tokens;
};
Rewriter.prototype.scanTokens = function(block) {
var i, token, tokens;
tokens = this.tokens;
@@ -31,6 +28,7 @@
}
return true;
};
Rewriter.prototype.detectEnd = function(i, condition, action) {
var levels, token, tokens, _ref, _ref2;
tokens = this.tokens;
@@ -39,9 +37,7 @@
if (levels === 0 && condition.call(this, token, i)) {
return action.call(this, token, i);
}
if (!token || levels < 0) {
return action.call(this, token, i - 1);
}
if (!token || levels < 0) return action.call(this, token, i - 1);
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
levels += 1;
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
@@ -51,19 +47,17 @@
}
return i - 1;
};
Rewriter.prototype.removeLeadingNewlines = function() {
var i, tag, _len, _ref;
_ref = this.tokens;
for (i = 0, _len = _ref.length; i < _len; i++) {
tag = _ref[i][0];
if (tag !== 'TERMINATOR') {
break;
}
}
if (i) {
return this.tokens.splice(0, i);
if (tag !== 'TERMINATOR') break;
}
if (i) return this.tokens.splice(0, i);
};
Rewriter.prototype.removeMidExpressionNewlines = function() {
return this.scanTokens(function(token, i, tokens) {
var _ref;
@@ -74,6 +68,7 @@
return 0;
});
};
Rewriter.prototype.closeOpenCalls = function() {
var action, condition;
condition = function(token, i) {
@@ -84,12 +79,11 @@
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'CALL_START') {
this.detectEnd(i + 1, condition, action);
}
if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
return 1;
});
};
Rewriter.prototype.closeOpenIndexes = function() {
var action, condition;
condition = function(token, i) {
@@ -100,12 +94,11 @@
return token[0] = 'INDEX_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'INDEX_START') {
this.detectEnd(i + 1, condition, action);
}
if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
return 1;
});
};
Rewriter.prototype.addImplicitBraces = function() {
var action, condition, stack, start, startIndent;
stack = [];
@@ -113,15 +106,16 @@
startIndent = 0;
condition = function(token, i) {
var one, tag, three, two, _ref, _ref2;
_ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
return false;
}
_ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
tag = token[0];
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
};
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;
@@ -150,53 +144,48 @@
return 2;
});
};
Rewriter.prototype.addImplicitParentheses = function() {
var action, noCall;
noCall = false;
action = function(token, i) {
var idx;
idx = token[0] === 'OUTDENT' ? i + 1 : i;
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
return this.tokens.splice(i, 0, ['CALL_END', ')', token[2]]);
};
return this.scanTokens(function(token, i, tokens) {
var callObject, current, next, prev, seenSingle, tag, _ref, _ref2, _ref3;
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
tag = token[0];
if (tag === 'CLASS' || tag === 'IF') {
noCall = true;
}
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
if (tag === 'CLASS' || tag === 'IF') noCall = true;
_ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
seenSingle = false;
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
noCall = false;
}
if (prev && !prev.spaced && tag === '?') {
token.call = true;
}
seenControl = false;
if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
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;
}
if (tag === 'IF' || tag === 'ELSE' || tag === '->' || tag === '=>') {
if (!seenSingle && token.fromThen) return true;
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
seenSingle = true;
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
seenControl = true;
}
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
return true;
}
return !token.generated && this.tag(i - 1) !== ',' && __indexOf.call(IMPLICIT_END, tag) >= 0 && (tag !== 'INDENT' || (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' && !seenControl)) && (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';
}
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
return 2;
});
};
Rewriter.prototype.addImplicitIndentation = function() {
return this.scanTokens(function(token, i, tokens) {
var action, condition, indent, outdent, starter, tag, _ref, _ref2;
@@ -216,27 +205,24 @@
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag;
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
if (starter === 'THEN') {
indent.fromThen = true;
}
if (starter === 'THEN') indent.fromThen = true;
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);
};
this.detectEnd(i + 2, condition, action);
if (tag === 'THEN') {
tokens.splice(i, 1);
}
if (tag === 'THEN') tokens.splice(i, 1);
return 1;
}
return 1;
});
};
Rewriter.prototype.tagPostfixConditionals = function() {
var condition;
condition = function(token, i) {
@@ -245,109 +231,58 @@
};
return this.scanTokens(function(token, i) {
var original;
if (token[0] !== 'IF') {
return 1;
}
if (token[0] !== 'IF') return 1;
original = token;
this.detectEnd(i + 1, condition, function(token, i) {
if (token[0] !== 'INDENT') {
return original[0] = 'POST_' + original[0];
}
if (token[0] !== 'INDENT') return original[0] = 'POST_' + original[0];
});
return 1;
});
};
Rewriter.prototype.ensureBalance = function(pairs) {
var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
levels = {};
openLine = {};
_ref = this.tokens;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
token = _ref[_i];
tag = token[0];
for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
_ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
levels[open] |= 0;
if (tag === open) {
if (levels[open]++ === 0) {
openLine[open] = token[2];
}
} else if (tag === close && --levels[open] < 0) {
throw Error("too many " + token[1] + " on line " + (token[2] + 1));
}
}
}
for (open in levels) {
level = levels[open];
if (level > 0) {
throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
}
}
return this;
};
Rewriter.prototype.rewriteClosingParens = function() {
var debt, key, stack;
stack = [];
debt = {};
for (key in INVERSES) {
debt[key] = 0;
}
return this.scanTokens(function(token, i, tokens) {
var inv, match, mtag, oppos, tag, val, _ref;
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
stack.push(token);
return 1;
}
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
return 1;
}
if (debt[inv = INVERSES[tag]] > 0) {
debt[inv] -= 1;
tokens.splice(i, 1);
return 0;
}
match = stack.pop();
mtag = match[0];
oppos = INVERSES[mtag];
if (tag === oppos) {
return 1;
}
debt[mtag] += 1;
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
if (this.tag(i + 2) === mtag) {
tokens.splice(i + 3, 0, val);
stack.push(match);
} else {
tokens.splice(i, 0, val);
}
return 1;
});
};
Rewriter.prototype.indentation = function(token) {
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
};
Rewriter.prototype.tag = function(i) {
var _ref;
return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
};
return Rewriter;
})();
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
INVERSES = {};
exports.INVERSES = INVERSES = {};
EXPRESSION_START = [];
EXPRESSION_END = [];
for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
_ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
EXPRESSION_START.push(INVERSES[rite] = left);
EXPRESSION_END.push(INVERSES[left] = rite);
}
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
IMPLICIT_UNSPACED_CALL = ['+', '-'];
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR', 'INDENT'];
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
}).call(this);

View File

@@ -1,8 +1,12 @@
(function() {
var Scope, extend, last, _ref;
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
exports.Scope = Scope = (function() {
Scope.root = null;
function Scope(parent, expressions, method) {
this.parent = parent;
this.expressions = expressions;
@@ -14,15 +18,12 @@
}
];
this.positions = {};
if (!this.parent) {
Scope.root = this;
}
if (!this.parent) Scope.root = this;
}
Scope.prototype.add = function(name, type, immediate) {
var pos;
if (this.shared && !immediate) {
return this.parent.add(name, type, immediate);
}
if (this.shared && !immediate) return this.parent.add(name, type, immediate);
if (typeof (pos = this.positions[name]) === 'number') {
return this.variables[pos].type = type;
} else {
@@ -32,27 +33,25 @@
}) - 1;
}
};
Scope.prototype.find = function(name, options) {
if (this.check(name, options)) {
return true;
}
if (this.check(name, options)) return true;
this.add(name, 'var');
return false;
};
Scope.prototype.parameter = function(name) {
if (this.shared && this.parent.check(name, true)) {
return;
}
if (this.shared && this.parent.check(name, true)) return;
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);
if (found || immediate) return found;
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
};
Scope.prototype.temporary = function(name, index) {
if (name.length > 1) {
return '_' + name + (index > 1 ? index : '');
@@ -60,26 +59,27 @@
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
}
};
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];
if (v.name === name) {
return v.type;
}
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;
}
return null;
};
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);
return temp;
};
Scope.prototype.assign = function(name, value) {
this.add(name, {
value: value,
@@ -87,34 +87,38 @@
});
return this.hasAssignments = true;
};
Scope.prototype.hasDeclarations = function() {
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);
}
}
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];
if (v.type.assigned) {
_results.push("" + v.name + " = " + v.type.value);
}
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
}
return _results;
};
return Scope;
})();
}).call(this);

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +0,0 @@
(function() {
var CoffeeScript, error, helpers, readline, repl, run, stdin, stdout;
CoffeeScript = require('./coffee-script');
helpers = require('./helpers');
readline = require('readline');
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');
}
} catch (err) {
error(err);
}
return repl.prompt();
};
process.on('uncaughtException', error);
if (readline.createInterface.length < 3) {
repl = readline.createInterface(stdin);
stdin.on('data', function(buffer) {
return repl.write(buffer);
});
} else {
repl = readline.createInterface(stdin, stdout);
}
repl.setPrompt('coffee> ');
repl.on('close', function() {
return stdin.destroy();
});
repl.on('line', run);
repl.prompt();
}).call(this);

View File

@@ -1,22 +1,31 @@
{
"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.3",
"licenses": [{
"type": "MIT",
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
}],
"engines": {
"node": ">=0.4.0"
},
"directories" : {
"lib" : "./lib/coffee-script"
},
"main" : "./lib/coffee-script/coffee-script",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"
},
"homepage": "http://coffeescript.org",
"repository": {
"type": "git",
"url": "git://github.com/jashkenas/coffee-script.git"
},
"devDependencies": {
"uglify-js": "1.0.6",
"jison": "0.2.11"
}
}

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

@@ -39,19 +39,19 @@ helpers.extend global,
missingTask name unless tasks[name]
tasks[name].action options
# Run `cake`. Executes all of the tasks you pass, in order. Note that Node's
# asynchrony may cause tasks to execute in a different order than you'd expect.
# If no tasks are passed, print the help screen.
# If no tasks are passed, print the help screen. Keep a reference to the
# original directory name, when running Cake tasks from subdirectories.
exports.run = ->
path.exists 'Cakefile', (exists) ->
throw new Error("Cakefile not found in #{process.cwd()}") unless exists
args = process.argv.slice 2
CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
oparse = new optparse.OptionParser switches
return printTasks() unless args.length
options = oparse.parse(args)
invoke arg for arg in options.arguments
global.__originalDirname = fs.realpathSync '.'
process.chdir cakefileDirectory __originalDirname
args = process.argv.slice 2
CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
oparse = new optparse.OptionParser switches
return printTasks() unless args.length
options = oparse.parse(args)
invoke arg for arg in options.arguments
# Display the list of Cake tasks in a format similar to `rake -T`
printTasks = ->
@@ -63,7 +63,15 @@ printTasks = ->
console.log "cake #{name}#{spaces} #{desc}"
console.log oparse.help() if switches.length
# Print an error and exit when attempting to all an undefined task.
# Print an error and exit when attempting to call an undefined task.
missingTask = (task) ->
console.log "No such task: \"#{task}\""
process.exit 1
# When `cake` is invoked, search in the current and all parent directories
# to find the relevant Cakefile.
cakefileDirectory = (dir) ->
return dir if path.existsSync path.join dir, 'Cakefile'
parent = path.normalize path.join dir, '..'
return cakefileDirectory parent unless parent is dir
throw new Error "Cakefile not found in #{process.cwd()}"

64
src/coffee-script.coffee Executable file → Normal file
View File

@@ -10,17 +10,18 @@ fs = require 'fs'
path = require 'path'
{Lexer,RESERVED} = require './lexer'
{parser} = require './parser'
vm = require 'vm'
# 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.3'
# Words that cannot be used as identifiers in CoffeeScript code
exports.RESERVED = RESERVED
@@ -53,26 +54,59 @@ exports.nodes = (source, options) ->
# Compile and execute a string of CoffeeScript (on the server), correctly
# setting `__filename`, `__dirname`, and relative `require()`.
exports.run = (code, options) ->
# We want the root module.
root = module
while root.parent
root = root.parent
mainModule = require.main
# Set the filename.
root.filename = if options.filename then fs.realpathSync(options.filename) else '.'
mainModule.filename = process.argv[1] =
if options.filename then fs.realpathSync(options.filename) else '.'
# Clear the module cache.
root.moduleCache = {} if root.moduleCache
mainModule.moduleCache and= {}
# Assign paths for node_modules loading
mainModule.paths = require('module')._nodeModulePaths path.dirname options.filename
# Compile.
if path.extname(root.filename) isnt '.coffee' or require.extensions
root._compile compile(code, options), root.filename
if path.extname(mainModule.filename) isnt '.coffee' or require.extensions
mainModule._compile compile(code, options), mainModule.filename
else
root._compile code, root.filename
mainModule._compile code, mainModule.filename
# 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 = {}) ->
return unless code = code.trim()
Script = vm.Script
if Script
if options.sandbox?
if options.sandbox instanceof Script.createContext().constructor
sandbox = options.sandbox
else
sandbox = Script.createContext()
sandbox[k] = v for own k, v of options.sandbox
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
else
sandbox = global
sandbox.__filename = options.filename || 'eval'
sandbox.__dirname = path.dirname sandbox.__filename
# define module/require only if they chose not to specify their own
unless sandbox isnt global or sandbox.module or sandbox.require
Module = require 'module'
sandbox.module = _module = new Module(options.modulename || 'eval')
sandbox.require = _require = (path) -> Module._load path, _module, true
_module.filename = sandbox.__filename
_require[r] = require[r] for r in Object.getOwnPropertyNames require when r isnt 'paths'
# use the same hack node currently uses for their own REPL
_require.paths = _module.paths = Module._nodeModulePaths process.cwd()
_require.resolve = (request) -> Module._resolveFilename request, _module
o = {}
o[k] = v for own k, v of options
o.bare = on # ensure return value
js = compile code, o
if sandbox is global
vm.runInThisContext js
else
vm.runInContext js, sandbox
# 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.
@@ -17,31 +17,33 @@ CoffeeScript = require './coffee-script'
helpers.extend CoffeeScript, new EventEmitter
printLine = (line) -> process.stdout.write line + '\n'
printWarn = (line) -> process.binding('stdio').writeError line + '\n'
printWarn = (line) -> process.stderr.write line + '\n'
# The help banner that is printed when `coffee` is called without arguments.
BANNER = '''
Usage: coffee [options] path/to/script.coffee
If called without options, `coffee` will run your script.
'''
# The list of all the valid option flags that `coffee` knows how to handle.
SWITCHES = [
['-b', '--bare', 'compile without a top-level function wrapper']
['-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']
['-e', '--eval', 'pass a string from the command line as input']
['-h', '--help', 'display this help message']
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint']
['-n', '--nodes', 'print out the parse tree that the parser produces']
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
['-o', '--output [DIR]', 'set the output directory for compiled JavaScript']
['-p', '--print', 'print out the compiled JavaScript']
['-r', '--require [FILE*]', 'require a library before executing your script']
['-s', '--stdio', 'listen for and compile scripts over stdio']
['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce']
['-v', '--version', 'display the version number']
['-w', '--watch', 'watch scripts for changes and rerun commands']
]
# Top-level objects shared by all the functions.
@@ -65,32 +67,58 @@ exports.run = ->
return require './repl' unless sources.length
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 = 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
# compile them. If a directory is passed, recursively compile all
# '.coffee' extension source files in it and all subdirectories.
compileScripts = ->
unprocessed = []
remaining_files = ->
total = 0
total += x for x in unprocessed
total
trackUnprocessedFiles = (sourceIndex, fileCount) ->
unprocessed[sourceIndex] ?= 0
unprocessed[sourceIndex] += fileCount
trackCompleteFiles = (sourceIndex, fileCount) ->
unprocessed[sourceIndex] -= fileCount
if opts.join
if helpers.compact(contents).length > 0 and remaining_files() == 0
compileJoin()
for source in sources
trackUnprocessedFiles sources.indexOf(source), 1
for source in sources
base = path.join(source)
compile = (source, topLevel) ->
compile = (source, sourceIndex, topLevel) ->
path.exists source, (exists) ->
if topLevel and not exists and source[-7..] isnt '.coffee'
return compile "#{source}.coffee", sourceIndex, topLevel
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) ->
throw err if err
trackUnprocessedFiles sourceIndex, files.length
for file in files
compile path.join(source, file)
compile path.join(source, file), sourceIndex
trackCompleteFiles sourceIndex, 1
else if topLevel or path.extname(source) is '.coffee'
fs.readFile source, (err, code) ->
throw err if err
if opts.join
contents[sources.indexOf source] = code.toString()
compileJoin() if helpers.compact(contents).length is sources.length
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n')
else
compileScript(source, code.toString(), base)
trackCompleteFiles sourceIndex, 1
watch source, base if opts.watch and not opts.join
compile source, true
else
trackCompleteFiles sourceIndex, 1
compile source, sources.indexOf(source), true
# Compile a single source script, containing the given code, according to the
# requested options. If evaluating the script directly sets `__filename`,
@@ -114,7 +142,7 @@ compileScript = (file, input, base) ->
CoffeeScript.emit 'failure', err, task
return if CoffeeScript.listeners('failure').length
return printLine err.message if o.watch
printWarn err.stack
printWarn err instanceof Error and err.stack or "ERROR: #{err}"
process.exit 1
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
@@ -131,7 +159,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 = ->
@@ -140,15 +168,22 @@ loadRequires = ->
require req for req in opts.require
module.filename = realFilename
# Watch a source CoffeeScript file using `fs.watchFile`, recompiling it every
# Watch a source CoffeeScript file using `fs.watch`, recompiling it every
# time the file is updated. May be used in combination with other options,
# such as `--lint` or `--print`.
watch = (source, base) ->
fs.watchFile source, {persistent: true, interval: 500}, (curr, prev) ->
return if curr.size is prev.size and curr.mtime.getTime() is prev.mtime.getTime()
fs.readFile source, (err, code) ->
throw err if err
compileScript(source, code.toString(), base)
fs.stat source, (err, prevStats)->
throw err if err
fs.watch source, (event) ->
if event is 'change'
fs.stat source, (err, stats) ->
throw err if err
return if stats.size is prevStats.size and
stats.mtime.getTime() is prevStats.mtime.getTime()
prevStats = stats
fs.readFile source, (err, code) ->
throw err if err
compileScript(source, code.toString(), base)
# Write out a JavaScript source file with the compiled code. By default, files
# are written out in `cwd` as `.js` files with the same name, but the output
@@ -165,7 +200,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
@@ -173,7 +208,7 @@ writeJs = (source, js, base) ->
# any errors or warnings that arise.
lint = (file, js) ->
printIt = (buffer) -> printLine file + ':\t' + buffer.toString().trim()
conf = __dirname + '/../extras/jsl.conf'
conf = __dirname + '/../../extras/jsl.conf'
jsl = spawn 'jsl', ['-nologo', '-stdin', '-conf', conf]
jsl.stdout.on 'data', printIt
jsl.stderr.on 'data', printIt

View File

@@ -84,7 +84,7 @@ grammar =
# All the different types of expressions in our language. The basic unit of
# CoffeeScript is the **Expression** -- everything that can be an expression
# is one. Block serve as the building blocks of many other rules, making
# is one. Blocks serve as the building blocks of many other rules, making
# them somewhat circular.
Expression: [
o 'Value'
@@ -120,7 +120,7 @@ grammar =
o 'STRING', -> new Literal $1
]
# All of our immediate values. These can (in general), be passed straight
# All of our immediate values. Generally these can be passed straight
# through and printed to JavaScript.
Literal: [
o 'AlphaNumeric'
@@ -201,6 +201,7 @@ grammar =
o 'ParamVar = Expression', -> new Param $1, $3
]
# Function Parameters
ParamVar: [
o 'Identifier'
o 'ThisProperty'
@@ -216,7 +217,7 @@ grammar =
# Variables and properties that can be assigned to.
SimpleAssignable: [
o 'Identifier', -> new Value $1
o 'Value Accessor', -> $1.push $2
o 'Value Accessor', -> $1.add $2
o 'Invocation Accessor', -> new Value $1, [$2]
o 'ThisProperty'
]
@@ -243,17 +244,20 @@ grammar =
Accessor: [
o '. Identifier', -> new Access $2
o '?. Identifier', -> new Access $2, 'soak'
o ':: Identifier', -> new Access $2, 'proto'
o ':: Identifier', -> [(new Access new Literal 'prototype'), new Access $2]
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.
@@ -274,14 +278,14 @@ grammar =
# Class definitions have optional bodies of prototype property assignments,
# and optional references to the superclass.
Class: [
o 'CLASS', -> new Class
o 'CLASS Block', -> new Class null, null, $2
o 'CLASS EXTENDS Value', -> new Class null, $3
o 'CLASS EXTENDS Value Block', -> new Class null, $3, $4
o 'CLASS SimpleAssignable', -> new Class $2
o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
o 'CLASS SimpleAssignable EXTENDS Value', -> new Class $2, $4
o 'CLASS SimpleAssignable EXTENDS Value Block', -> new Class $2, $4, $5
o 'CLASS', -> new Class
o 'CLASS Block', -> new Class null, null, $2
o 'CLASS EXTENDS Expression', -> new Class null, $3
o 'CLASS EXTENDS Expression Block', -> new Class null, $3, $4
o 'CLASS SimpleAssignable', -> new Class $2
o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
o 'CLASS SimpleAssignable EXTENDS Expression', -> new Class $2, $4
o 'CLASS SimpleAssignable EXTENDS Expression Block', -> new Class $2, $4, $5
]
# Ordinary function invocation, or a chained series of calls.
@@ -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,
@@ -350,7 +354,7 @@ grammar =
o 'ArgList OptComma INDENT ArgList OptComma OUTDENT', -> $1.concat $4
]
# Valid arguments are Block or Splats.
# Valid arguments are Blocks or Splats.
Arg: [
o 'Expression'
o 'Splat'
@@ -569,7 +573,7 @@ operators = [
# Wrapping Up
# -----------
# Finally, now what we have our **grammar** and our **operators**, we can create
# Finally, now that we have our **grammar** and our **operators**, we can create
# our **Jison.Parser**. We do this by processing all of our rules, recording all
# terminals (every symbol which does not appear as the name of a rule above)
# as "tokens".

View File

@@ -7,7 +7,7 @@
#
# Which is a format that can be fed directly into [Jison](http://github.com/zaach/jison).
{Rewriter} = require './rewriter'
{Rewriter, INVERSES} = require './rewriter'
# Import the helpers we need.
{count, starts, compact, last} = require './helpers'
@@ -41,6 +41,7 @@ exports.Lexer = class Lexer
@indebt = 0 # The over-indentation at the current level.
@outdebt = 0 # The under-outdentation at the current level.
@indents = [] # The stack of all current indentation levels.
@ends = [] # The stack for pairing up tokens.
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.
# At every position, run through this list of attempted matches,
@@ -60,6 +61,7 @@ exports.Lexer = class Lexer
@literalToken()
@closeIndentation()
@error "missing #{tag}" if tag = @ends.pop()
return @tokens if opts.rewrite is off
(new Rewriter).rewrite @tokens
@@ -80,11 +82,11 @@ 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
not forcedIdentifier and id in COFFEE_KEYWORDS
if not forcedIdentifier and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS)
tag = id.toUpperCase()
if tag is 'WHEN' and @tag() in LINE_BREAK
tag = 'LEADING_WHEN'
@@ -104,16 +106,16 @@ exports.Lexer = class Lexer
@tokens.pop()
id = '!' + id
if id in JS_FORBIDDEN
if id in ['eval', 'arguments'].concat JS_FORBIDDEN
if forcedIdentifier
tag = 'IDENTIFIER'
id = new String id
id.reserved = yes
else if id in RESERVED
@identifierError id
@error "reserved word \"#{word}\""
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'
@@ -131,8 +133,11 @@ exports.Lexer = class Lexer
numberToken: ->
return 0 unless match = NUMBER.exec @chunk
number = match[0]
lexedLength = number.length
if binaryLiteral = /0b([01]+)/.exec number
number = (parseInt binaryLiteral[1], 2).toString()
@token 'NUMBER', number
number.length
lexedLength
# Matches strings, including multi-line strings. Ensures that quotation marks
# are balanced within the string's contents, and within nested interpolations.
@@ -170,11 +175,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.
@@ -188,19 +193,26 @@ exports.Lexer = class Lexer
# JavaScript and Ruby.
regexToken: ->
return 0 if @chunk.charAt(0) isnt '/'
return @heregexToken match if match = HEREGEX.exec @chunk
if match = HEREGEX.exec @chunk
length = @heregexToken match
@line += count match[0], '\n'
return length
prev = last @tokens
return 0 if prev and (prev[0] in (if prev.spaced then NOT_REGEX else NOT_SPACED_REGEX))
return 0 unless match = REGEX.exec @chunk
[regex] = match
@token 'REGEX', if regex is '//' then '/(?:)/' else regex
regex.length
[match, regex, flags] = match
if regex[..1] is '/*' then @error 'regular expressions cannot begin with `*`'
if regex is '//' then regex = '/(?:)/'
@token 'REGEX', "#{regex}#{flags}"
match.length
# Matches multiline extended regular expressions.
heregexToken: (match) ->
[heregex, body, flags] = match
if 0 > body.indexOf '#{'
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/')
if re.match /^\*/ then @error 'regular expressions cannot begin with `*`'
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}"
return heregex.length
@token 'IDENTIFIER', 'RegExp'
@@ -235,6 +247,7 @@ exports.Lexer = class Lexer
return 0 unless match = MULTI_DENT.exec @chunk
indent = match[0]
@line += count indent, '\n'
@seenFor = no
prev = last @tokens, 1
size = indent.length - 1 - indent.lastIndexOf '\n'
noNewlines = @unfinished()
@@ -249,6 +262,7 @@ exports.Lexer = class Lexer
diff = size - @indent + @outdebt
@token 'INDENT', diff
@indents.push diff
@ends .push 'OUTDENT'
@outdebt = @indebt = 0
else
@indebt = 0
@@ -258,7 +272,7 @@ exports.Lexer = class Lexer
# Record an outdent token or multiple tokens, if we happen to be moving back
# inwards past several recorded indents.
outdentToken: (moveOut, noNewlines, close) ->
outdentToken: (moveOut, noNewlines) ->
while moveOut > 0
len = @indents.length - 1
if @indents[len] is undefined
@@ -273,8 +287,10 @@ exports.Lexer = class Lexer
dent = @indents.pop() - @outdebt
moveOut -= dent
@outdebt = 0
@pair 'OUTDENT'
@token 'OUTDENT', dent
@outdebt -= moveOut if dent
@tokens.pop() while @value() is ';'
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR' or noNewlines
this
@@ -289,6 +305,7 @@ exports.Lexer = class Lexer
# Generate a newline token. Consecutive newlines get merged together.
newlineToken: ->
@tokens.pop() while @value() is ';'
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR'
this
@@ -312,12 +329,15 @@ exports.Lexer = class Lexer
tag = value
prev = last @tokens
if value is '=' and prev
@assignmentError() if not prev[1].reserved and prev[1] in JS_FORBIDDEN
if not prev[1].reserved and prev[1] in JS_FORBIDDEN
@error "reserved word \"#{@value()}\" can't be assigned"
if prev[1] in ['||', '&&']
prev[0] = 'COMPOUND_ASSIGN'
prev[1] += '='
return value.length
if value is ';' then tag = 'TERMINATOR'
if value is ';'
@seenFor = no
tag = 'TERMINATOR'
else if value in MATH then tag = 'MATH'
else if value in COMPARE then tag = 'COMPARE'
else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN'
@@ -332,7 +352,9 @@ exports.Lexer = class Lexer
tag = 'INDEX_START'
switch prev[0]
when '?' then prev[0] = 'INDEX_SOAK'
when '::' then prev[0] = 'INDEX_PROTO'
switch value
when '(', '{', '[' then @ends.push INVERSES[value]
when ')', '}', ']' then @pair value
@token tag, value
value.length
@@ -343,8 +365,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
@error "block comment cannot contain \"*/\", starting"
return doc if doc.indexOf('\n') <= 0
else
while match = HEREDOC_INDENT.exec doc
attempt = match[1]
indent = attempt if indent is null or 0 < attempt.length < indent.length
@@ -367,25 +392,16 @@ 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
else return this
this
# Close up all remaining open blocks at the end of the file.
closeIndentation: ->
@outdentToken @indent
# The error for when you try to use a forbidden word in JavaScript as
# an identifier.
identifierError: (word) ->
throw SyntaxError "Reserved word \"#{word}\" on line #{@line + 1}"
# The error for when you try to assign to a reserved word in JavaScript,
# like "function" or "default".
assignmentError: ->
throw SyntaxError "Reserved word \"#{@value()}\" on line #{@line + 1} can't be assigned"
# Matches a balanced group such as a single or double-quoted string. Pass in
# a series of delimiters, all of which must be nested correctly within the
# contents of the string. This method allows us to have strings within
@@ -405,13 +421,14 @@ exports.Lexer = class Lexer
continue
if end is '}' and letter in ['"', "'"]
stack.push end = letter
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str.slice i) or REGEX.exec(str.slice i))
i += match[0].length - 1
else if end is '}' and letter is '{'
stack.push end = '}'
else if end is '"' and prev is '#' and letter is '{'
stack.push end = '}'
prev = letter
throw new Error "missing #{ stack.pop() }, starting on line #{ @line + 1 }"
@error "missing #{ stack.pop() }, starting"
# Expand variables and expressions inside double-quoted strings using
# Ruby-like notation for substitution of arbitrary expressions.
@@ -460,6 +477,21 @@ exports.Lexer = class Lexer
@token ')', ')' if interpolated
tokens
# Pairs up a closing token, ensuring that all listed pairs of tokens are
# correctly balanced throughout the course of the token stream.
pair: (tag) ->
unless tag is wanted = last @ends
@error "unmatched #{tag}" unless 'OUTDENT' is wanted
# Auto-close INDENT to support syntax like this:
#
# el.click((event) ->
# el.hide())
#
@indent -= size = last @indents
@outdentToken size, true
return @pair tag
@ends.pop()
# Helpers
# -------
@@ -478,9 +510,8 @@ exports.Lexer = class Lexer
# Are we in the midst of an unfinished expression?
unfinished: ->
LINE_CONTINUER.test(@chunk) or
(prev = last @tokens, 1) and prev[0] isnt '.' and
(value = @value()) and not value.reserved and
NO_NEWLINE.test(value) and not CODE.test(value) and not ASSIGNED.test(@chunk)
@tag() in ['\\', '.', '?.', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
'COMPARE', 'LOGIC', 'COMPOUND_ASSIGN', 'THROW', 'EXTENDS']
# Converts newlines for string literals.
escapeLines: (str, heredoc) ->
@@ -493,6 +524,10 @@ exports.Lexer = class Lexer
if contents in ['\n', quote] then contents else match
body = body.replace /// #{quote} ///g, '\\$&'
quote + @escapeLines(body, heredoc) + quote
# Throws a syntax error on the current `@line`.
error: (message) ->
throw SyntaxError "#{message} on line #{ @line + 1}"
# Constants
# ---------
@@ -508,7 +543,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 : '=='
@@ -519,6 +555,9 @@ COFFEE_KEYWORDS.push op for op of COFFEE_ALIASES =
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,
# to avoid having a JavaScript error at runtime.
@@ -542,7 +581,8 @@ IDENTIFIER = /// ^
NUMBER = ///
^ 0x[\da-f]+ | # hex
^ (?: \d+(\.\d+)? | \.\d+ ) (?:e[+-]?\d+)? # decimal
^ 0b[01]+ | # binary
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
///i
HEREDOC = /// ^ ("""|''') ([\s\S]*?) (?:\n[^\n\S]*)? \1 ///
@@ -571,7 +611,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
@@ -581,7 +621,7 @@ REGEX = /// ^
]
) [^ [ / \n \\ ]*
)*
/ [imgy]{0,4} (?!\w)
/) ([imgy]{0,4}) (?!\w)
///
HEREGEX = /// ^ /{3} ([\s\S]+?) /{3} ([imgy]{0,4}) (?!\w) ///
@@ -593,18 +633,12 @@ MULTILINER = /\n/g
HEREDOC_INDENT = /\n+([^\n\S]*)/g
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/
HEREDOC_ILLEGAL = /\*\//
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?!\.) | :: ) ///
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///
TRAILING_SPACES = /\s+$/
NO_NEWLINE = /// ^ (?: # non-capturing group
[-+*&|/%=<>!.\\][<>=&|]* | # symbol operators
and | or | is(?:nt)? | n(?:ot|ew) | # word operators
delete | typeof | instanceof
) $ ///
# Compound assignment tokens.
COMPOUND_ASSIGN = [
'-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='
@@ -643,7 +677,7 @@ NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']']
# force a division parse:
NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING'
# Tokens which could legitimately be invoked or indexed. A opening
# Tokens which could legitimately be invoked or indexed. An opening
# parentheses or bracket following these tokens will be recorded as the start
# of a function invocation or indexing operation.
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,7 @@ exports.OptionParser = class OptionParser
@rules = buildRules rules
# Parse the list of arguments, populating an `options` object with all of the
# specified options, and returning it. `options.arguments` will be an array
# specified options, and return it. `options.arguments` will be an array
# containing the remaining non-option arguments. `options.literals` will be
# an array of options that are meant to be passed through directly to the
# executing script. This is a simpler API than many option parsers that allow
@@ -25,10 +25,13 @@ exports.OptionParser = class OptionParser
# for interpreting the options object.
parse: (args) ->
options = arguments: [], literals: []
args = normalizeArguments args
originalArgs = args
args = normalizeArguments args
for arg, i in args
if arg is '--'
options.literals = args[(i + 1)..]
pos = originalArgs.indexOf '--'
options.arguments = [originalArgs[1 + pos]]
options.literals = originalArgs[(2 + pos)..]
break
isOption = !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG))
matchedRule = no
@@ -40,7 +43,7 @@ exports.OptionParser = class OptionParser
break
throw new Error "unrecognized option: #{arg}" if isOption and not matchedRule
if not isOption
options.arguments = args.slice i
options.arguments = originalArgs[(originalArgs.indexOf arg)..]
break
options

View File

@@ -6,42 +6,118 @@
# 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'
Module = require 'module'
# REPL Setup
# Config
REPL_PROMPT = 'coffee> '
REPL_PROMPT_CONTINUATION = '......> '
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'
stdout.write (err.stack or err.toString()) + '\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) ->
if !buffer.toString().trim() and !backlog
repl.prompt()
return
code = backlog += buffer
if code[code.length - 1] is '\\'
backlog = "#{backlog[...-1]}\n"
repl.setPrompt REPL_PROMPT_CONTINUATION
repl.prompt()
return
repl.setPrompt REPL_PROMPT
backlog = ''
try
val = CoffeeScript.eval buffer.toString(), bare: on, globals: on, filename: 'repl'
process.stdout.write val + '\n' if val isnt undefined
_ = global._
returnValue = CoffeeScript.eval "_=(#{code}\n)", {
filename: 'repl'
modulename: 'repl'
}
if returnValue is undefined
global._ = _
process.stdout.write inspect(returnValue, 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
completions = getCompletions prefix, Object.getOwnPropertyNames val
[completions, prefix]
# Attempt to autocomplete an in-scope free variable: `one`.
completeVariable = (text) ->
free = (text.match SIMPLEVAR)?[1]
if free?
vars = Script.runInThisContext 'Object.getOwnPropertyNames(this)'
keywords = (r for r in CoffeeScript.RESERVED when r[0..1] isnt '__')
possibilities = vars.concat keywords
completions = getCompletions free, possibilities
[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)
# 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()
repl.on 'line', run
repl.on 'attemptClose', ->
if backlog
backlog = ''
process.stdout.write '\n'
repl.setPrompt REPL_PROMPT
repl.prompt()
else
repl.close()
repl.on 'close', ->
process.stdout.write '\n'
stdin.destroy()
repl.on 'line', run
repl.setPrompt REPL_PROMPT
repl.prompt()

View File

@@ -3,7 +3,7 @@
# the resulting parse table. Instead of making the parser handle it all, we take
# a series of passes over the token stream, using this **Rewriter** to convert
# shorthand into the unambiguous long form, add implicit indentation and
# parentheses, balance incorrect nestings, and generally clean things up.
# parentheses, and generally clean things up.
# The **Rewriter** class is used by the [Lexer](lexer.html), directly against
# its internal array of tokens.
@@ -26,8 +26,6 @@ class exports.Rewriter
@tagPostfixConditionals()
@addImplicitBraces()
@addImplicitParentheses()
@ensureBalance BALANCED_PAIRS
@rewriteClosingParens()
@tokens
# Rewrite the token stream, looking one token ahead and behind.
@@ -104,7 +102,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]
@@ -130,19 +131,19 @@ class exports.Rewriter
# deal with them.
addImplicitParentheses: ->
noCall = no
action = (token, i) ->
idx = if token[0] is 'OUTDENT' then i + 1 else i
@tokens.splice idx, 0, ['CALL_END', ')', token[2]]
action = (token, i) -> @tokens.splice i, 0, ['CALL_END', ')', token[2]]
@scanTokens (token, i, tokens) ->
tag = token[0]
noCall = yes if tag in ['CLASS', 'IF']
[prev, current, next] = tokens[i - 1 .. i + 1]
callObject = not noCall and tag is 'INDENT' and
next and next.generated and next[0] is '{' and
prev and prev[0] in IMPLICIT_FUNC
seenSingle = no
noCall = no if tag in LINEBREAKS
token.call = yes if prev and not prev.spaced and tag is '?'
callObject = not noCall and tag is 'INDENT' and
next and next.generated and next[0] is '{' and
prev and prev[0] in IMPLICIT_FUNC
seenSingle = no
seenControl = no
noCall = no if tag in LINEBREAKS
token.call = yes if prev and not prev.spaced and tag is '?'
return 1 if token.fromThen
return 1 unless callObject or
prev?.spaced and (prev.call or prev[0] in IMPLICIT_FUNC) and
(tag in IMPLICIT_CALL or not (token.spaced or token.newLine) and tag in IMPLICIT_UNSPACED_CALL)
@@ -150,9 +151,11 @@ class exports.Rewriter
@detectEnd i + 1, (token, i) ->
[tag] = token
return yes if not seenSingle and token.fromThen
seenSingle = yes if tag in ['IF', 'ELSE', '->', '=>']
seenSingle = yes if tag in ['IF', 'ELSE', 'CATCH', '->', '=>']
seenControl = yes if tag in ['IF', 'ELSE', 'SWITCH', 'TRY']
return yes if tag in ['.', '?.', '::'] and @tag(i - 1) is 'OUTDENT'
not token.generated and @tag(i - 1) isnt ',' and tag in IMPLICIT_END and
not token.generated and @tag(i - 1) isnt ',' and (tag in IMPLICIT_END or
(tag is 'INDENT' and not seenControl)) and
(tag isnt 'INDENT' or
(@tag(i - 2) isnt 'CLASS' and @tag(i - 1) not in IMPLICIT_BLOCK and
not ((post = @tokens[i + 1]) and post.generated and post[0] is '{')))
@@ -204,65 +207,6 @@ class exports.Rewriter
original[0] = 'POST_' + original[0] if token[0] isnt 'INDENT'
1
# Ensure that all listed pairs of tokens are correctly balanced throughout
# the course of the token stream.
ensureBalance: (pairs) ->
levels = {}
openLine = {}
for token in @tokens
[tag] = token
for [open, close] in pairs
levels[open] |= 0
if tag is open
openLine[open] = token[2] if levels[open]++ is 0
else if tag is close and --levels[open] < 0
throw Error "too many #{token[1]} on line #{token[2] + 1}"
for open, level of levels when level > 0
throw Error "unclosed #{ open } on line #{openLine[open] + 1}"
this
# We'd like to support syntax like this:
#
# el.click((event) ->
# el.hide())
#
# In order to accomplish this, move outdents that follow closing parens
# inwards, safely. The steps to accomplish this are:
#
# 1. Check that all paired tokens are balanced and in order.
# 2. Rewrite the stream with a stack: if you see an `EXPRESSION_START`, add it
# to the stack. If you see an `EXPRESSION_END`, pop the stack and replace
# it with the inverse of what we've just popped.
# 3. Keep track of "debt" for tokens that we manufacture, to make sure we end
# up balanced in the end.
# 4. Be careful not to alter array or parentheses delimiters with overzealous
# rewriting.
rewriteClosingParens: ->
stack = []
debt = {}
debt[key] = 0 for key of INVERSES
@scanTokens (token, i, tokens) ->
if (tag = token[0]) in EXPRESSION_START
stack.push token
return 1
return 1 unless tag in EXPRESSION_END
if debt[inv = INVERSES[tag]] > 0
debt[inv] -= 1
tokens.splice i, 1
return 0
match = stack.pop()
mtag = match[0]
oppos = INVERSES[mtag]
return 1 if tag is oppos
debt[mtag] += 1
val = [oppos, if mtag is 'INDENT' then match[1] else oppos]
if @tag(i + 2) is mtag
tokens.splice i + 3, 0, val
stack.push match
else
tokens.splice i, 0, val
1
# Generate the indentation tokens, based on another token on the same line.
indentation: (token) ->
[['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]]
@@ -286,7 +230,7 @@ BALANCED_PAIRS = [
# The inverse mappings of `BALANCED_PAIRS` we're trying to fix up, so we can
# look things up from either end.
INVERSES = {}
exports.INVERSES = INVERSES = {}
# The tokens that signal the start/end of a balanced pair.
EXPRESSION_START = []
@@ -315,7 +259,7 @@ IMPLICIT_UNSPACED_CALL = ['+', '-']
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']
# Tokens that always mark the end of an implicit call for single-liners.
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR', 'INDENT']
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']
# Single-line flavors of block expressions that have unclosed endings.
# The grammar can't disambiguate them, so we insert the implicit indentation.

Some files were not shown because too many files have changed in this diff Show More