Compare commits

..

309 Commits
0.2.1 ... 0.2.2

Author SHA1 Message Date
Jeremy Ashkenas
24408c785a caught a close call bug with object comprehensions and not specifying the value 2010-01-10 17:44:19 -05:00
Jeremy Ashkenas
bb5bf7f94f more docs, more tests 2010-01-10 17:36:06 -05:00
Jeremy Ashkenas
3e987de4a8 rebuilding underscore.coffee docs, adding a build task -- need to remember to copy over nicer headers 2010-01-10 17:23:07 -05:00
Jeremy Ashkenas
de74bce2cd more docs for 0.2.2 2010-01-10 17:14:20 -05:00
Jeremy Ashkenas
c265b7d5d6 updating comprehension speed test with the new normal comprehensions 2010-01-10 16:39:38 -05:00
Jeremy Ashkenas
ad18378f7e adding '::' as shorthand for '.prototype.' 2010-01-10 16:16:59 -05:00
Jeremy Ashkenas
902febb43a big commit -- adding back object comprehensions, using 'ino', versus 'in' for array comprehensions, fixing bug with dollar signs in identifiers 2010-01-10 15:52:23 -05:00
Jeremy Ashkenas
13fc8aea04 removing object comprehensions from CoffeeScript, they were necessitating the generation of too much ugly JS 2010-01-10 14:45:44 -05:00
Jeremy Ashkenas
8ea75290b5 better indentation for compile_closure 2010-01-10 13:18:44 -05:00
Jeremy Ashkenas
9498ef9fe4 ignoring 'presentation' folder 2010-01-10 12:21:06 -05:00
Jeremy Ashkenas
8e3922b6c6 allowing comments in the middle of switch statements 2010-01-09 13:25:44 -05:00
Jeremy Ashkenas
2319affa61 allowing chained calls broken up over multiple lines with periods at the front (jQuery-style) 2010-01-09 12:12:38 -05:00
Jeremy Ashkenas
7befbddae2 adding test for body-less while, using null as the body so JSLint doesn't get in a tizzy 2010-01-09 11:58:50 -05:00
Jeremy Ashkenas
ae58e2ec6c adding body-less while expressions 2010-01-09 11:51:32 -05:00
Jeremy Ashkenas
4c3f00cf77 fixing calling super from constructors 2010-01-08 10:54:44 -05:00
Jeremy Ashkenas
8b3926fb0c making extends equivalent to the Google Closure version 2010-01-08 09:35:02 -05:00
Jeremy Ashkenas
d416c184db separating out the --no-wrap and the --globals arguments, which shouldn't be jammed together 2010-01-07 21:10:25 -05:00
Jeremy Ashkenas
30dca132bd more node cleaning, using idt() instead of TAB 2010-01-07 20:57:23 -05:00
Jeremy Ashkenas
69908be85c cleaned up nodes.rb indentation code with an idt method 2010-01-07 20:55:30 -05:00
Jeremy Ashkenas
c70b6f39b1 weepy's new speedy comprehensions 2010-01-07 20:27:26 -05:00
Jeremy Ashkenas
fab98a2219 mentioning the racc gem in the readme 2010-01-07 09:43:44 -05:00
Jeremy Ashkenas
18c3e79a50 adding automatic 'return this' for constructors: functions that start with a Capital Letter 2010-01-06 23:47:36 -05:00
Jeremy Ashkenas
9ed8020b84 added the constructor fix for capitalized functions 2010-01-06 23:34:56 -05:00
Jeremy Ashkenas
cf7079a379 fixing the lexer to handle strings that end with a backslash character 2010-01-06 23:15:13 -05:00
Jeremy Ashkenas
3e33b4a618 adding a warning about parser.rb to the readme 2010-01-06 22:57:21 -05:00
Jeremy Ashkenas
a5c1922200 printing a warning when the parser goes missing 2010-01-06 22:41:09 -05:00
Jeremy Ashkenas
c49f2d8097 ignoring the generated parser.rb 2010-01-06 22:38:03 -05:00
Jeremy Ashkenas
eb9b18376e removing the parser.rb from revision control -- it's taking up too much space -- you'll have to generate it yourself with rake build:parser 2010-01-06 22:37:25 -05:00
Jeremy Ashkenas
fbcdc12a9c adding empty return statements -- they return null 2010-01-06 21:21:42 -05:00
Matt Lyon
41bb6edcd2 next time: don't copy the .tmDelta over the .tmLanguage 2010-01-06 00:11:20 -08:00
Matt Lyon
22d3238b2a if we escape the close-brackets, it won't think single-line objects need folding 2010-01-06 00:03:11 -08:00
Matt Lyon
3124869e1d add folding for multi-line object literals 2010-01-05 22:44:44 -08:00
Jeremy Ashkenas
de49465dc6 comments 2010-01-06 01:27:58 -05:00
Jeremy Ashkenas
4fc40e4841 adding the 'in' operator 2010-01-05 23:29:43 -05:00
Jeremy Ashkenas
0275e7775f fixing weepy's comment scenario 2010-01-05 23:15:32 -05:00
Jeremy Ashkenas
001e42b85c fixing range literals by making them values, not expressions, and adding tests 2010-01-05 22:49:51 -05:00
Jeremy Ashkenas
46f1977ea1 adding ranges as expressions, they get expanded into the equivalent array 2010-01-05 22:17:09 -05:00
Jeremy Ashkenas
c2bb93b5f8 ellipsis is the new splat 2010-01-05 21:40:36 -05:00
Jeremy Ashkenas
1040e52246 CoffeeScript 0.2.1 2010-01-05 09:30:48 -05:00
Jeremy Ashkenas
d555685030 docs for arguments conversion 2010-01-05 09:29:10 -05:00
Jeremy Ashkenas
5fe419b1ce automatic conversion of arguments into arrays 2010-01-05 09:10:45 -05:00
Jeremy Ashkenas
1ebc4d5f21 alright, done fiddling. CoffeeScript 0.2.0 2010-01-05 00:45:04 -05:00
Jeremy Ashkenas
6658250c8e more docs 2010-01-05 00:34:18 -05:00
Jeremy Ashkenas
724d4c9660 tweaking docs 2010-01-05 00:19:22 -05:00
Jeremy Ashkenas
0cf7801f36 more docs for 0.2 -- blocks and splats 2010-01-04 23:26:27 -05:00
Jeremy Ashkenas
ae603749be adding the complete underscore.coffee example to the docs 2010-01-04 22:51:02 -05:00
Jeremy Ashkenas
6e63a18f86 first pass at 0.2.0 docs 2010-01-04 22:19:45 -05:00
Jeremy Ashkenas
3e24cef69f minor doc updates -- let's try pulling in the underscore test suite 2010-01-04 19:15:24 -05:00
Jeremy Ashkenas
2c1033f5da removed the whole messy notions of looking downwards for returns or children -- ForNodes now peek at top-level status, and if they're being asked to return a value from the outside 2010-01-04 18:57:10 -05:00
Jeremy Ashkenas
da9e38808c nicer scope inspects 2010-01-04 09:43:50 -05:00
Jeremy Ashkenas
5efaff506c more underscore 2010-01-04 01:43:45 -05:00
Jeremy Ashkenas
94bc7c1f92 putting in a special check for returns within array comprehensions -- not very nice 2010-01-04 01:06:31 -05:00
Jeremy Ashkenas
f75d98e447 pretty amazing -- fully functional draft of underscore.js 0.5.2, all in CoffeeScript 2010-01-04 00:28:52 -05:00
Jeremy Ashkenas
69283fcadd fixing a nasty little bug with not dup'ing a string in Scope.rb, causing later functions to start their free_variables where previous functions left off, because they shared their ancestor's @temp_variable string 2010-01-04 00:16:38 -05:00
Jeremy Ashkenas
672dd70bdb more underscore examples raised a slight bug with a lexing ambiguity between leading whens (in switches), and trailing whens (in comprehensions) -- made two different tokens to distinguish them 2010-01-03 22:25:38 -05:00
Jeremy Ashkenas
32cd15f038 mo' expression examples 2010-01-03 19:08:41 -05:00
Jeremy Ashkenas
ecdb47107b -- 2010-01-03 19:00:08 -05:00
Jeremy Ashkenas
cb1815885c adding a statement-as-expression test, and returning null from while loops, if asked 2010-01-03 18:58:34 -05:00
Jeremy Ashkenas
d53d85d03e updating fixtures -- all tests now pass -- back to master 2010-01-03 18:49:00 -05:00
Jeremy Ashkenas
8e6486a1d7 logic error in Expressions was causing over-compilation by a factor of the depth of the tree 2010-01-03 18:47:23 -05:00
Jeremy Ashkenas
97f16c0e9c fixing comment-within-objecta-and-array-literal printing for the new expression regime. 2010-01-03 18:35:03 -05:00
Jeremy Ashkenas
bd2597c6b8 change lexical scoping example to use var names that haven't been already defined 2010-01-03 18:27:26 -05:00
Jeremy Ashkenas
56015bd23f subtle call order bug was preventing variable declarations 2010-01-03 18:22:10 -05:00
Jeremy Ashkenas
3724778989 lowering the precedence of if/else/while 2010-01-03 18:11:53 -05:00
Jeremy Ashkenas
bb0dfa5cd4 removing the silly newlines from comments 2010-01-03 18:07:03 -05:00
Jeremy Ashkenas
6160fe3c17 beautiful -- all examples, tests, and docs are now compiling without JSLint warnings 2010-01-03 16:32:59 -05:00
Jeremy Ashkenas
099944e0aa All execution tests are now passing with statements everywhere 2010-01-03 15:59:33 -05:00
Jeremy Ashkenas
4814d5baa5 more progress -- you can wrap parentheses around statements now 2010-01-03 15:13:59 -05:00
Jeremy Ashkenas
78c4957ba8 first rough rough rough draft of kamatsu's closure suggestion -- test.coffee runs, but probably nothing else 2010-01-03 13:59:17 -05:00
Jeremy Ashkenas
de4eddcad4 bumping version numbers to 0.2.0 in anticipation of release soon-ish 2010-01-03 11:01:50 -05:00
Jeremy Ashkenas
ba3c5298f7 adding a block test and using PARAM_SPLAT to remove the last shift/reduce conflict 2010-01-03 10:46:37 -05:00
Jeremy Ashkenas
21a0cc83ae Adding kamatsu's proposed block literal syntax 2010-01-03 10:19:39 -05:00
Jeremy Ashkenas
7eff8786bc todo 2010-01-02 01:00:03 -05:00
Jeremy Ashkenas
7ee5be674d adding splice literals, with tests 2010-01-02 00:20:24 -05:00
Jeremy Ashkenas
38520bfece rebuilding narwhal uncovered a bug with named functions 2010-01-01 22:00:34 -05:00
Jeremy Ashkenas
c3d0e50e8f fixing the food/eat array comprehension in the docs to not pretend like there's a made-up method on String.prototype 2010-01-01 17:16:34 -05:00
Jeremy Ashkenas
34add7d7bf adding consistent highlighting to variable assignment, whether functions or values 2010-01-01 17:11:48 -05:00
Jeremy Ashkenas
75d9e23df4 better existence test, with tests 2010-01-01 12:41:55 -05:00
Jeremy Ashkenas
ff80f8d423 adding the notion of existence -- postfixing an expression with a question mark will check if to see if it's not null or undefined 2010-01-01 12:31:05 -05:00
Jeremy Ashkenas
3489eec6ee commenting the lexer a bit more 2010-01-01 12:11:35 -05:00
Jeremy Ashkenas
2f69bc1708 expanding the list of tokens that regexes may not follow, according to the Mozilla JS 2.0 docs 2010-01-01 12:08:36 -05:00
Jeremy Ashkenas
0f81dbe913 adding steps to range comprehensions 2010-01-01 11:54:59 -05:00
Jeremy Ashkenas
e30a267c9d fixing precedence order, so that you can nest range comprehensions 2010-01-01 11:19:57 -05:00
Jeremy Ashkenas
305f883eab making range comprehensions compile safely, even when you assign to the same variable as your endposts. 2010-01-01 10:55:43 -05:00
Jeremy Ashkenas
f622fc43bc -- 2010-01-01 10:40:29 -05:00
Jeremy Ashkenas
a93a570603 allowing indentation within function calls 2010-01-01 10:38:28 -05:00
Jeremy Ashkenas
02fbd28e58 adding a test for expressions in range comprehensions 2010-01-01 10:20:29 -05:00
Jeremy Ashkenas
2cef93b381 test for uminus 2010-01-01 10:17:33 -05:00
Jeremy Ashkenas
caf9d627cb allowing expressions within range literals 2010-01-01 10:15:22 -05:00
Jeremy Ashkenas
ad5b5fa458 fixing the regex lexer to make it less agressive when we know it can't possibly be a regex 2010-01-01 09:49:18 -05:00
Jeremy Ashkenas
41056ca2bd fix for multiple splats in a function call 2009-12-31 20:02:15 -05:00
Jeremy Ashkenas
409283a30f adding splats as arguments to function calls 2009-12-31 19:52:13 -05:00
Jeremy Ashkenas
abfc9f5a2d adding a note in the docs about how to build the parser and install the gem 2009-12-31 18:22:51 -05:00
Jeremy Ashkenas
43edd29d22 comment about test_execution being the most important 2009-12-31 18:09:48 -05:00
Jeremy Ashkenas
26c89cef06 reserving variables for splats the regular way, not through a custom 'var' declaration 2009-12-31 18:03:39 -05:00
Jeremy Ashkenas
1d2bb3b2be adding splats to function definitions 2009-12-31 17:50:12 -05:00
Jeremy Ashkenas
f299972713 expressions nested in expressions made for some indentation issues -- statements are now responsible for their own leading indentation 2009-12-31 16:50:46 -05:00
Jeremy Ashkenas
bfd7455db4 adding a test for multiline-array-comprehension-with-filter 2009-12-31 16:13:52 -05:00
Jeremy Ashkenas
7ec91a1ee5 enabling multi-line array and object comprehensions 2009-12-31 16:09:27 -05:00
Jeremy Ashkenas
44fec922a4 adding a filtered object comprehension test 2009-12-31 15:08:54 -05:00
Jeremy Ashkenas
07d0044718 using push for comprehension results so that it works with object keys, and adding a test for object comprehensions 2009-12-31 15:03:32 -05:00
Jeremy Ashkenas
00538bd62c adding weepy's suggestion to use (for .. in) for array comprehensions, which means that they're now object comprehensions as well 2009-12-31 14:52:14 -05:00
Jeremy Ashkenas
4e8a12d70d done commenting the rewriter 2009-12-31 13:45:07 -05:00
Jeremy Ashkenas
edf1fc769f detailed scan_tokens so that the calling function can indicate the number of spaces to move forward (or backward) in the token stream 2009-12-31 13:43:24 -05:00
Jeremy Ashkenas
2231d67cef making assignment token detection a regex like all the others 2009-12-31 13:26:38 -05:00
Jeremy Ashkenas
a376e7f4a3 pulled out all token-stream-rewriting logic into the CoffeeScript::Rewriter -- let the lexer be simpleminded 2009-12-31 13:22:33 -05:00
Jeremy Ashkenas
20ade4f448 adding a rake:ultraviolet build syntax highlighter task, and regenerating the docs with correct highlighting 2009-12-31 13:01:10 -05:00
Jeremy Ashkenas
f9d630119d adding a test case for named functions 2009-12-31 10:52:00 -05:00
Jeremy Ashkenas
7f76c22894 updating docs -- need to get back on the computer that has the syntax highlighter for UV installed 2009-12-30 23:43:55 -05:00
Jeremy Ashkenas
b1fa06ff70 updating tests for named functions 2009-12-30 23:14:29 -05:00
Jeremy Ashkenas
e481a39a0d making all functions named functions, if children of an immediate assignment 2009-12-30 23:13:22 -05:00
Jeremy Ashkenas
8762162dff adding proper auto-newline escaping 2009-12-30 22:49:25 -05:00
Jeremy Ashkenas
a6539a030c allowing any manner of indentation in the comments, by adjusting them in the lexer 2009-12-30 22:24:40 -05:00
Jeremy Ashkenas
942572d081 don't print the confusing indentation numbers when raising ParseErrors for indentation 2009-12-30 21:57:03 -05:00
Jeremy Ashkenas
ec60205014 getting there, finally ... all tests are green for whitespace 2009-12-30 21:51:23 -05:00
Jeremy Ashkenas
dba8439425 the underscore example parses now -- added line number information to parenthetical nodes 2009-12-30 21:44:51 -05:00
Jeremy Ashkenas
774e3d3e31 moving the newline escaping detection up higher so indents don't overrule it 2009-12-30 21:41:01 -05:00
Jeremy Ashkenas
cae0b1a038 lex indents with higher precedence than comments 2009-12-30 21:20:30 -05:00
Jeremy Ashkenas
bbbfd92373 more fiddling with the lexer -- the indentation is super fragile 2009-12-30 21:15:54 -05:00
Jeremy Ashkenas
fd83759ef4 more fiddling with the lexer -- the indentation is super fragile 2009-12-30 21:11:54 -05:00
Jeremy Ashkenas
49714656e1 rolling back MULTI_DENT regex 2009-12-30 20:41:32 -05:00
Jeremy Ashkenas
d43d491561 regex cleanup -- eliminating some lookahead because Ruby regexps blow chunks (stackoverflows) when you look (ahead) at them funny. 2009-12-30 20:36:47 -05:00
Jeremy Ashkenas
c8711b419e fixed up the comment/assignment interleaving in nodes.rb 2009-12-30 20:24:24 -05:00
Jeremy Ashkenas
5c7b77aa4d rewrote 'rewrite_closing_parens' with an explicit loop -- there was a bug when adding to @tokens in the middle of scan_tokens' while loop -- consider scan_tokens to be on probation until further notice 2009-12-30 20:12:30 -05:00
Jeremy Ashkenas
dc821f2e4c be more vigorous about removing mid-expression newlines, 'when' closes implicit blocks, a better comment-detecting regex lexer that doesn't eat outdents 2009-12-30 19:26:37 -05:00
Jeremy Ashkenas
cd68f02981 big milestone. examples/code.coffee now compiles correctly under the new whitespace regime 2009-12-30 18:59:33 -05:00
Jeremy Ashkenas
e6cd32f2fc balancing parens closing single-line blocks 2009-12-30 18:52:03 -05:00
Jeremy Ashkenas
ed1c1f7a0e fixing up documents example 2009-12-30 18:28:16 -05:00
Jeremy Ashkenas
5659d1bd49 adding ')' as a SINGLE_CLOSER, although it's probably unsafe 2009-12-30 18:09:43 -05:00
Jeremy Ashkenas
9a7c075e06 parser and test tweaks for whitespace -- tests are coming along 2009-12-30 17:58:27 -05:00
Jeremy Ashkenas
62c51006a1 removed the final shift/reduce errors -- back to zero for the first time in a long time 2009-12-30 17:45:47 -05:00
Jeremy Ashkenas
d528db76e6 special case for 'else if' in the lexer 2009-12-30 17:41:14 -05:00
Jeremy Ashkenas
9a946d2ac5 execution tests still pass -- more lexer block insertion and 2 shift/reduces in the grammar now 2009-12-30 15:52:07 -05:00
Jeremy Ashkenas
c822f96145 patching up the lexer and adding a test with trailing whitespace (it was too string for trailing whitespace before) 2009-12-30 15:10:47 -05:00
Jeremy Ashkenas
9e3ef42c63 fixing up narwhal integration (again) 2009-12-30 15:05:05 -05:00
Jeremy Ashkenas
f93e552cb3 fixin up narwhal factory and adding more implicit blocks to the lexer 2009-12-30 14:32:59 -05:00
Jeremy Ashkenas
ea58be2838 patched up lexer to add indentation to single-line flavors of statements -- let's expand this idea 2009-12-30 13:58:00 -05:00
Jeremy Ashkenas
4d514f255b merged in master branch again 2009-12-30 13:38:50 -05:00
Jeremy Ashkenas
ce0e71f796 fixing the double-printing bug with coffee -r 2009-12-30 13:34:25 -05:00
Jeremy Ashkenas
7c97f32dd3 ignoring test.coffee 2009-12-30 12:59:05 -05:00
Jeremy Ashkenas
6ddd808f74 removing dots from whitespace examples 2009-12-30 00:22:27 -05:00
Jeremy Ashkenas
90051e9096 clean up a couple of test errors for whitespace 2009-12-30 00:08:49 -05:00
Jeremy Ashkenas
dd3c9abe15 touch-ups cleanups to the lexer and rebuilding the narwhal libs from whitespace'd versions 2009-12-29 23:01:08 -05:00
Jeremy Ashkenas
d3ab60df78 implementing kamatsu's debt-based lexer for closing delimiters 2009-12-29 22:24:52 -05:00
Jeremy Ashkenas
541291e2f3 whitespace parser down to 4 shift/reduce errors -- good enough for me 2009-12-29 21:46:15 -05:00
Jeremy Ashkenas
fd357871f2 put the commas on the outside of expression closers 2009-12-29 20:39:51 -05:00
Jeremy Ashkenas
f5aafc6591 don't break trailing commas with rewrite_closing_parens 2009-12-29 10:20:18 -05:00
Jeremy Ashkenas
96803d0129 killing some newlines in the execution tests, to test the lexer's newline suppression 2009-12-29 10:02:19 -05:00
Jeremy Ashkenas
ae112d6087 changing array comprehension filters from 'where' to 'when' to mirror case/when 2009-12-29 09:55:37 -05:00
Jeremy Ashkenas
a3129e05ae allowing indentation in object and array literals 2009-12-29 09:25:56 -05:00
Jeremy Ashkenas
f44443b58a still some kinks to work out -- mid-expression blocks 2009-12-29 09:18:41 -05:00
Jeremy Ashkenas
3fbb870d01 using 'where' for array comprehension filtering, after kamatsu's suggestion -- execution tests pass now with significant whitespace 2009-12-29 08:52:26 -05:00
Jeremy Ashkenas
cea417de02 moving along with whitespace 2009-12-28 23:08:02 -05:00
Jeremy Ashkenas
ddd52a1845 first draft of kamatsu's rewrite rules -- finally got whitespace to be flexible enough, I think. 2009-12-28 21:07:47 -05:00
Jeremy Ashkenas
50bdd2668c got lexer balancing parens, indent/outdents, brackets, and curlies 2009-12-28 21:02:40 -05:00
Jeremy Ashkenas
bb84a982ce merging in master 2009-12-28 20:06:23 -05:00
Jeremy Ashkenas
7b5b261743 removed unused example 2009-12-28 20:05:14 -05:00
Jeremy Ashkenas
c84bb0c875 fixing relative path for execution tests 2009-12-28 16:23:48 -05:00
Jeremy Ashkenas
a186e47e2c stop shifting args 2009-12-28 16:20:11 -05:00
Jeremy Ashkenas
41f3d54f4a rebuilding narwhal libs 2009-12-28 16:10:56 -05:00
Jeremy Ashkenas
9e47f6bd58 merging in tlrobinson's fix for package.json 2009-12-28 16:09:14 -05:00
tlrobinson
3762f4c680 Add package.json to gemspec files so Narwhal integrations works when installed as a gem. 2009-12-28 12:45:47 -08:00
Jeremy Ashkenas
845c8cba3b removing broken accidental commit 2009-12-28 09:02:55 -08:00
tlrobinson
a722b42eed Add package on command line in case it's not installed in a Narwhal packages path. 2009-12-28 01:49:07 -08:00
tlrobinson
78e08f316d Merge branch 'master' of git://github.com/jashkenas/coffee-script 2009-12-28 01:36:23 -08:00
tlrobinson
55616cf3b8 Fixed Narwhal integration. Cleaned up module organization, etc. 2009-12-28 01:16:57 -08:00
Jeremy Ashkenas
aa45456d7d part of the way to supporting multiline array comprehensions -- the grammar and parsing is there -- the code generation is tricky 2009-12-27 21:50:02 -08:00
Jeremy Ashkenas
ac00a19514 CoffeeScript 0.1.6 -- bugfixes 2009-12-27 12:49:11 -08:00
Jeremy Ashkenas
7ae8687a3e fixing paths for running
coffee compiles CoffeeScript source files into JavaScript.

Usage:
  coffee path/to/script.coffee
    -i, --interactive                run a CoffeeScript REPL (requires Narwhal)
    -r, --run                        compile and run a script (requires Narwhal)
    -o, --output [DIR]               set the directory for compiled JavaScript
    -w, --watch                      watch scripts for changes, and recompile
    -p, --print                      print the compiled JavaScript to stdout
    -l, --lint                       pipe the compiled JavaScript through JSLint
    -e, --eval                       compile a cli scriptlet or read from stdin
    -t, --tokens                     print the tokens that the lexer produces
    -v, --verbose                    print at every step of code generation
    -n, --no-wrap                    raw output, no safety wrapper or vars
        --install-bundle             install the CoffeeScript TextMate bundle
        --version                    display CoffeeScript version
    -h, --help                       display this help message outside of the coffee-script directory
2009-12-27 12:43:05 -08:00
Jeremy Ashkenas
55e736cb27 more underscore examples 2009-12-27 11:01:19 -08:00
Jeremy Ashkenas
3ee4e98ccc more underscore and bugfix edits to code generation 2009-12-26 22:24:21 -08:00
Jeremy Ashkenas
d7dd18b476 more underscore, and removing custom_assign and return from conditional compilation 2009-12-26 21:55:56 -08:00
Jeremy Ashkenas
097bede5c8 coffeescript 0.1.5, just for kicks 2009-12-26 21:25:37 -08:00
Jeremy Ashkenas
983dac84a2 docs for range comprehensiosn 2009-12-26 20:46:31 -08:00
Jeremy Ashkenas
eeef8d3612 got negative ranges working with (much, much) uglier compiled code 2009-12-26 20:35:43 -08:00
Jeremy Ashkenas
b4250c0f02 that's it for now for significant whitespace -- I really just can't make flexible enough 2009-12-26 19:29:59 -08:00
Jeremy Ashkenas
cc0c92d20d smarter but uglier lexer -- now handles most significant whitespace cases. Clean it up though... (newlines after outdents) 2009-12-26 13:22:53 -08:00
Jeremy Ashkenas
694833dbd0 removing no_paren -- it was optimizing away order of operations 2009-12-26 11:55:34 -08:00
Jeremy Ashkenas
fde9852090 removing no_paren -- can cause order of operations errors 2009-12-26 11:10:59 -08:00
Jeremy Ashkenas
191875a85b got a lexer working along the lines of what kamatsu proposes 2009-12-26 10:59:47 -08:00
Jeremy Ashkenas
556f8cb68a little more progress on whitespace 2009-12-26 10:49:11 -08:00
Jeremy Ashkenas
5bed5646be merging in master 2009-12-26 09:59:06 -08:00
Jeremy Ashkenas
08dddb27a0 adding newline escaping, with tests 2009-12-26 09:29:03 -08:00
Jeremy Ashkenas
2a1fc4b1b7 docs 2009-12-26 09:05:57 -08:00
Jeremy Ashkenas
3c67d54bbe changed bin/coffee-script to bin/coffee 2009-12-26 08:57:13 -08:00
Jeremy Ashkenas
6a30d48ced fixed range comprehension indexing 2009-12-26 00:27:49 -08:00
Jeremy Ashkenas
d59ef71642 trading the cs> prompt for the coffee> prompt 2009-12-26 00:18:24 -08:00
Jeremy Ashkenas
ff78546465 added array comprehensions over ranges 2009-12-26 00:16:40 -08:00
Jeremy Ashkenas
834442148b docs for assignment-as-expression 2009-12-25 23:17:34 -08:00
Jeremy Ashkenas
adaae0ccae major internal reworking -- all variable declarations have been pushed up to the first line of the block scope -- all assignment is now an inherent expression 2009-12-25 22:57:33 -08:00
Jeremy Ashkenas
7c132d65dc started raising syntax errors for parens wrapped around expressions (they used to silently be ignored) 2009-12-25 20:36:22 -08:00
Jeremy Ashkenas
b58102c514 don't add the no_wrap key to the options hash unless we're going to use it 2009-12-25 19:48:47 -08:00
Jeremy Ashkenas
52700ca922 comment 2009-12-25 19:34:40 -08:00
Jeremy Ashkenas
dd5317ebe9 documenting ranges and slices 2009-12-25 16:35:57 -08:00
Jeremy Ashkenas
1ba7c77136 reorganizing test fixtures and adding range literals for array slices 2009-12-25 16:20:28 -08:00
Jeremy Ashkenas
62485c2b8c CoffeeScript 0.1.4 2009-12-25 14:43:24 -08:00
Jeremy Ashkenas
d46bf8ee71 moved the coffeescript extension over from .cs to .coffee -- let's leave C# in peace. Changed array comprehensions to always return their mapped result, even when unassigned 2009-12-25 14:18:05 -08:00
Jeremy Ashkenas
e494d520ea stopped using __proto__, instead, using a variant of goog.inherits for extends and super() 2009-12-25 13:57:47 -08:00
Jeremy Ashkenas
f55b4cd8b6 ForBody is really the ForSource 2009-12-25 13:40:57 -08:00
Jeremy Ashkenas
763e04fec9 cleaned up the for grammar and eliminated a shift/reduce conflict 2009-12-25 13:39:33 -08:00
Jeremy Ashkenas
4b5db1181c make equals signs full equals of colons -- you can use them inside of object literals now too 2009-12-25 13:21:17 -08:00
Jeremy Ashkenas
bc6ec37272 allowing = to assign 2009-12-25 07:42:27 -08:00
Jeremy Ashkenas
55bf0a2c61 going back to familiar operators +: is just too strange 2009-12-25 07:31:51 -08:00
Jeremy Ashkenas
968aeec523 added a test to make sure that chained calls work 2009-12-25 07:16:59 -08:00
Jeremy Ashkenas
851ec82495 allowing chained function calls, one right after another 2009-12-25 07:08:57 -08:00
Jeremy Ashkenas
c4ba971d39 bumping to 0.1.3 ... here we go 2009-12-25 00:16:56 -08:00
Jeremy Ashkenas
e7e8e243a2 better error warnings on the command line 2009-12-25 00:02:27 -08:00
Jeremy Ashkenas
73aaf127c8 removed bin/cs in favor of a more comprehensive coffee-script command ... now with --interactive and --run 2009-12-24 23:57:27 -08:00
Jeremy Ashkenas
7a0de52c96 majorly cleaned up the CoffeeScript that defines the Narwhal integration 2009-12-24 23:28:01 -08:00
Jeremy Ashkenas
2d57ee693b the narwhal integration written in JavaScript has been replaced with CoffeeScript, and compiler-generated variable names now start with '__' 2009-12-24 23:09:24 -08:00
Jeremy Ashkenas
d8ceb3b4bb sped up the execution test a good deal by running it all in one pass 2009-12-24 22:29:30 -08:00
Jeremy Ashkenas
beae912a91 making all assignment-y operators use a colon -- now it's +: -: *: /:, and friends 2009-12-24 22:25:29 -08:00
Jeremy Ashkenas
6865f5be92 removed dependency on v8 in favor of bin/cs 2009-12-24 22:08:32 -08:00
tlrobinson
2f35bba083 Print compiler errors to stderr 2009-12-24 19:34:17 -08:00
Jeremy Ashkenas
378e156e11 fixed the bin/cs repl to save assignment between commands by using the new --no-wrap 2009-12-24 17:45:23 -08:00
Jeremy Ashkenas
9b2326492b the --no-wrap option now disables top-level var declarations 2009-12-24 17:37:24 -08:00
Jeremy Ashkenas
93009e07f6 updating docs for isnt 2009-12-24 17:22:46 -08:00
Jeremy Ashkenas
985e0a080b trading aint for isnt -- let's be serious 2009-12-24 17:21:20 -08:00
Jeremy Ashkenas
95bfb0b45c allowing quoted strings within object assignment, a in JS and JSON 2009-12-24 17:14:53 -08:00
Jeremy Ashkenas
65e9ba4c30 bumping to 0.1.2 to get the super()/extends fix out there 2009-12-24 17:05:55 -08:00
Jeremy Ashkenas
1c83e68292 got extends back in the language -- use it together with super 2009-12-24 16:49:23 -08:00
Jeremy Ashkenas
47812d9ea6 fixing super() calls, thanks to tolmasky 2009-12-24 16:23:23 -08:00
Jeremy Ashkenas
a80b532a05 removing the special-case std-reading in favor of '--eval' 2009-12-24 15:49:42 -08:00
Jeremy Ashkenas
42ca566d26 document that -e can read from stdin 2009-12-24 15:35:58 -08:00
Jeremy Ashkenas
e27756cee8 with a working -n --no-wrap option to disable the top-level function safety wrapper 2009-12-24 15:31:00 -08:00
Jeremy Ashkenas
46f81c2de1 Merge branch 'master' of git://github.com/tlrobinson/coffee-script 2009-12-24 15:05:56 -08:00
Jeremy Ashkenas
c3ff752c40 ... 2009-12-24 15:05:14 -08:00
Jeremy Ashkenas
73a0777705 outdent lexing is correct now, I think 2009-12-24 14:51:53 -08:00
tlrobinson
9f80998415 Command line CoffeeScript 2009-12-24 14:42:57 -08:00
tlrobinson
dbccc1fa4f Narwhal support for CoffeeScript 2009-12-24 14:41:35 -08:00
tlrobinson
08248180f9 Read from stdin if source is "-" 2009-12-24 14:40:39 -08:00
Jeremy Ashkenas
ed504ea6be added and -> &&, or -> || to the docs (they were missing) 2009-12-24 14:37:30 -08:00
Jeremy Ashkenas
da84906d1e this might not work for ))) outdent cases 2009-12-24 14:34:48 -08:00
Jeremy Ashkenas
aafd3cd6ea first, totally broken branch of significant whitespace -- it can handle examples/whitespace.cs though 2009-12-24 13:48:46 -08:00
Jeremy Ashkenas
39ceca477d docs for 0.1.1 2009-12-24 12:02:28 -08:00
Jeremy Ashkenas
bfb24c6b5d bumping to 0.1.1 2009-12-24 11:59:19 -08:00
Jeremy Ashkenas
7f502543d2 added the typeof operater as an OpNode 2009-12-24 11:50:44 -08:00
Jeremy Ashkenas
5d1ec9d2a9 added the instanceof operator to the grammar as an operation node 2009-12-24 11:46:51 -08:00
Jeremy Ashkenas
2e8f03b4cc another wish 2009-12-24 10:31:44 -08:00
Jeremy Ashkenas
840e2b89fc docs 2009-12-24 09:56:44 -08:00
Jeremy Ashkenas
c438123a3d added a wish list to the docs 2009-12-24 09:54:12 -08:00
Jeremy Ashkenas
726a9b229e doc tweaks 2009-12-24 01:38:32 -08:00
Jeremy Ashkenas
8d76f4bd3f changing switch/case to switch/when -- it's a better word 2009-12-24 01:33:59 -08:00
Jeremy Ashkenas
849f0e4192 added comprehensive linting to the test suit 2009-12-24 00:49:11 -08:00
Jeremy Ashkenas
47928ca952 fixed the broken try/catch grammar 2009-12-24 00:45:16 -08:00
Jeremy Ashkenas
fb13a303f2 with a more comprehensive execution test that uncovered some missing spots 2009-12-24 00:41:12 -08:00
Jeremy Ashkenas
b743e3219a added some execution test 2009-12-24 00:12:07 -08:00
Jeremy Ashkenas
417753bd62 added readme 2009-12-23 23:12:29 -08:00
Jeremy Ashkenas
705b293982 first draft of docs are done 2009-12-23 23:01:39 -08:00
Jeremy Ashkenas
0a58eeef2b waypoint 2009-12-24 01:22:41 -05:00
Jeremy Ashkenas
b1f3ad24a2 added git st with the new operator regex 2009-12-24 00:37:33 -05:00
Jeremy Ashkenas
2b94849429 ported over a little more underscore 2009-12-23 21:09:32 -05:00
Jeremy Ashkenas
eae53d4787 added the ! sign as an allowed operator 2009-12-23 21:00:04 -05:00
Jeremy Ashkenas
5f9a190683 ... 2009-12-23 20:57:35 -05:00
Jeremy Ashkenas
cdfb5091be more better super docs, better switch docs 2009-12-23 20:48:55 -05:00
Jeremy Ashkenas
64879cdc66 added yes, no, on and off as boolean aliases and a nice aliases section to the docs 2009-12-23 20:24:55 -05:00
Jeremy Ashkenas
a4d014549b broken waypoint, but fixed line numbers with the new JS comments 2009-12-23 19:42:44 -05:00
Jeremy Ashkenas
60eabf63cf broken waypoint, but fixed line numbers with the new JS comments 2009-12-23 19:42:18 -05:00
Jeremy Ashkenas
6555473788 for whatever reason, don't need to force else-bodies to compile as statements anymore ... let them do what they want 2009-12-22 12:18:27 -05:00
Jeremy Ashkenas
e916d4648d removed all traces of 'extends' -- it's not any shorter or more convenient than just setting the prototype 2009-12-22 12:08:29 -05:00
Jeremy Ashkenas
ec58d6fda2 got comments within object and array literals working out 2009-12-22 11:50:43 -05:00
Jeremy Ashkenas
65809d08f6 first draft of parsing and printing along comments -- unfortunately, not yet working within objects and arrays 2009-12-22 11:27:19 -05:00
Jeremy Ashkenas
d45643c527 passing through comments as tags on Values, but not printing them out quite yet... 2009-12-22 10:48:58 -05:00
Jeremy Ashkenas
9b8f018646 nice -- it's pushing down assignments properly (recursively) now 2009-12-22 10:16:53 -05:00
Jeremy Ashkenas
2f211196a2 moderate refactor of nodes.rb -- tests pass and examples compile without warnings 2009-12-22 10:11:41 -05:00
Jeremy Ashkenas
9bb3e3fbe8 clean up children at exit -- had about twenty processes all watching and recompiling the docs 2009-12-21 12:15:13 -05:00
Jeremy Ashkenas
c7fa9c320a documentation waypoint 2009-12-21 11:41:45 -05:00
Jeremy Ashkenas
dcc70e5ab0 added full complement of bitwise operators 2009-12-19 22:56:27 -05:00
Jeremy Ashkenas
93bdfcb72a added full complement of bitwise operators 2009-12-19 22:55:58 -05:00
Jeremy Ashkenas
9ba1ffde21 making the each fixture a little more like underscore, and avoiding passing assignment into functions from the outside 2009-12-19 00:45:36 -05:00
Jeremy Ashkenas
0b2e7f1e59 added the verbose option to the CLI 2009-12-19 00:37:54 -05:00
Jeremy Ashkenas
b2e6a34d40 more little fixes, lots of subtle things, added a verbose logging mode 2009-12-19 00:33:34 -05:00
Jeremy Ashkenas
ad3b887df4 lots of tweaks make the tests pass again 2009-12-18 23:13:59 -05:00
Jeremy Ashkenas
6f81ac3684 patched up array comprehensions somewhat. Parens are still a necessary evil, and there's still probably plenty of edge cases 2009-12-18 22:30:09 -05:00
Jeremy Ashkenas
2f75854a61 little fixes more examples 2009-12-18 09:55:31 -05:00
Jeremy Ashkenas
253e45fc54 adding css for syntax highlighting 2009-12-18 08:36:20 -05:00
Jeremy Ashkenas
31639d7d1a todo to-done 2009-12-18 07:40:26 -05:00
Jeremy Ashkenas
6ba5d45cbe finished the first draft of the parser test 2009-12-18 07:28:26 -05:00
Jeremy Ashkenas
f154ab3d15 adding comprehensive attr_readers to the AST for testing 2009-12-18 07:21:59 -05:00
Jeremy Ashkenas
669c065dd7 parser test raises some minor improvements (remove unnecessary ValueNode arrays, etc 2009-12-18 07:11:01 -05:00
Jeremy Ashkenas
92adabdddc adding an initial lexer test 2009-12-18 06:59:06 -05:00
Jeremy Ashkenas
049358d006 after a lot of grammar wrestling, got the if-else chains to parse unambiguously. Now you only need a single period to close chains of any length. 2009-12-18 00:49:23 -05:00
Jeremy Ashkenas
a50446a0ca finally got the function/object/variable assignment indentation straightened out, I think 2009-12-17 23:45:24 -05:00
Jeremy Ashkenas
67bb49ed04 compiling if-else chains into nice flat ones 2009-12-17 23:34:52 -05:00
Jeremy Ashkenas
1395b05d36 first major rework of the nodes -- still need more comments and templatish cleanup, but character tagging is all settled 2009-12-17 23:22:02 -05:00
Jeremy Ashkenas
83944950ac renamed Nodes to Expressions 2009-12-17 22:58:40 -05:00
Jeremy Ashkenas
d124f7fc0d finished commenting everything but the nodes -- they're up next 2009-12-17 22:54:24 -05:00
Jeremy Ashkenas
77704d24a2 finished commenting the grammar 2009-12-17 22:22:35 -05:00
Jeremy Ashkenas
68bc68c1ac many more comments, plus a fix for inner-assignment indentation 2009-12-17 22:13:29 -05:00
Jeremy Ashkenas
8511a33b1e commented the command-line interface 2009-12-17 21:57:21 -05:00
Jeremy Ashkenas
6050cad0f8 moved the TextMate bundle into the gem, added a command to install it 2009-12-17 21:46:12 -05:00
Jeremy Ashkenas
9976de76f5 added the 'delete' operator 2009-12-17 21:21:07 -05:00
Jeremy Ashkenas
0dc445138b removed the 'default' keyword in favor of an 'else' 2009-12-17 21:14:36 -05:00
Jeremy Ashkenas
3ffbf541df removed class checks in favor of statement? 2009-12-17 21:10:49 -05:00
Jeremy Ashkenas
e3c667d49d number examples 2009-12-17 21:00:31 -05:00
Jeremy Ashkenas
2c90e8b002 added exponential and hex numbers 2009-12-17 20:59:19 -05:00
Jeremy Ashkenas
398251ff90 added a nice --watch mode to continually recompile or relint (or reprint) your coffeescripts 2009-12-17 20:37:39 -05:00
Jeremy Ashkenas
9249ceaef5 cleanups getting underscore to compile 2009-12-17 10:33:57 -05:00
Jeremy Ashkenas
1eec05d23a added nice syntax errors 2009-12-17 10:04:43 -05:00
Jeremy Ashkenas
1590713576 passing through values with line number information that look and act like Ruby natives 2009-12-17 09:37:42 -05:00
Jeremy Ashkenas
146b5694c2 cleaned up lexer in order to add line numbers 2009-12-17 09:29:49 -05:00
Jeremy Ashkenas
1d35910567 added the ability to super() 2009-12-17 09:07:42 -05:00
Jeremy Ashkenas
1a8311b9d0 allowing inner slashes in regexes 2009-12-17 08:29:19 -05:00
Jeremy Ashkenas
4e1e119f58 supporting escaped quotes in strings 2009-12-17 08:26:46 -05:00
Jeremy Ashkenas
3dac0f6d84 supporting escaped quotes in strings 2009-12-17 08:26:20 -05:00
Jeremy Ashkenas
962885444e multiline strings 2009-12-17 08:23:17 -05:00
Jeremy Ashkenas
d1682f5b3f multiline strings 2009-12-17 08:23:07 -05:00
Jeremy Ashkenas
c6f11fbfeb built the first gem -- works just fine 2009-12-16 23:10:03 -05:00
Jeremy Ashkenas
290aa257de completely reorganized for a gem and the 'coffee-script' command 2009-12-16 22:42:53 -05:00
49 changed files with 990 additions and 3004 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
presentation
test.coffee
parser.output
lib/coffee_script/parser.rb
test/fixtures/underscore
*.gem

3
README
View File

@@ -36,3 +36,6 @@
The source repository:
git://github.com/jashkenas/coffee-script.git
To build CoffeeScript from source, install the "racc" gem and
run "rake build:parser". Then bin/coffee will work.

View File

@@ -29,6 +29,11 @@ namespace :build do
sh "sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax"
end
desc "Rebuild the Underscore.coffee documentation page"
task :underscore do
sh "uv -s coffeescript -t idle -h examples/underscore.coffee > documentation/underscore.html"
end
end
desc "Build the documentation page"

View File

@@ -1,7 +1,7 @@
Gem::Specification.new do |s|
s.name = 'coffee-script'
s.version = '0.2.1' # Keep version in sync with coffee-script.rb
s.date = '2010-1-5'
s.version = '0.2.2' # Keep version in sync with coffee-script.rb
s.date = '2010-1-10'
s.homepage = "http://jashkenas.github.com/coffee-script/"
s.summary = "The CoffeeScript Compiler"

View File

@@ -1,3 +1,3 @@
# The first ten global properties.
globals: (name for property, name in window)[0...10]
globals: (name for name ino window)[0...10]

View File

@@ -2,5 +2,5 @@ alert(
try
nonexistent / undefined
catch error
"The error is: " + error
"Caught an error: " + error
)

View File

@@ -1,3 +1,3 @@
years_old: {max: 10, ida: 9, tim: 11}
ages: child + " is " + age for age, child in years_old
ages: child + " is " + age for child, age ino years_old

View File

@@ -19,7 +19,7 @@ math: {
}
# Splats:
race: winner, *runners =>
race: winner, runners... =>
print(winner, runners)
# Existence:

View File

@@ -1,3 +1,6 @@
for i in [0...eggs.length] by 12
dozen_eggs: eggs[i...i+12]
deliver(new egg_carton(dozen))
countdown: num for num in [10..1]
egg_delivery: =>
for i in [0...eggs.length] by 12
dozen_eggs: eggs[i...i+12]
deliver(new egg_carton(dozen))

View File

@@ -1,6 +1,6 @@
gold: silver: the_field: "unknown"
medalists: first, second, *rest =>
medalists: first, second, rest... =>
gold: first
silver: second
the_field: rest
@@ -18,7 +18,7 @@ contenders: [
"Usain Bolt"
]
medalists(*contenders)
medalists(contenders...)
alert("Gold: " + gold)
alert("Silver: " + silver)

View File

@@ -1,16 +1,16 @@
Animal: =>
Animal.prototype.move: meters =>
Animal::move: meters =>
alert(this.name + " moved " + meters + "m.")
Snake: name => this.name: name
Snake extends Animal
Snake.prototype.move: =>
Snake::move: =>
alert("Slithering...")
super(5)
Horse: name => this.name: name
Horse extends Animal
Horse.prototype.move: =>
Horse::move: =>
alert("Galloping...")
super(45)

View File

@@ -1,18 +1,3 @@
<%#
TODO:
Multiline and nested array comprehensions (and filters with 'when').
Range comprehension examples (expression endpoints), with steps.
Object comprehension examples.
Significant Whitespace Rules.
Newline-delimited Matrix.
Automatic newline escaping.
All functions are named functions.
Splats in function definitions.
(Multiple) splats as arguments to a function call.
Exists?
Array assignment splice literals.
%>
<%
require 'uv'
def code_for(file, executable=false)
@@ -55,8 +40,8 @@
<p>
<b>Disclaimer:</b>
CoffeeScript is just for fun and seriously alpha. I'm sure that there are still
plenty of holes in the lexer and leaks in the syntax. <i>There is no guarantee,
explicit or implied, of its suitability for any purpose.</i> That said,
plenty of holes in the walls and leaks in the roof. <i>There are no guarantees
that the syntax won't change between versions.</i> That said,
it compiles into clean JavaScript (the good parts) that can use existing
JavaScript libraries seamlessly, and passes through
<a href="http://www.jslint.com/">JSLint</a> without warnings. The compiled
@@ -66,7 +51,7 @@
<p>
<b>Latest Version:</b>
<a href="http://gemcutter.org/gems/coffee-script">0.2.1</a>
<a href="http://gemcutter.org/gems/coffee-script">0.2.2</a>
</p>
<h2>Table of Contents</h2>
@@ -82,7 +67,7 @@
<a href="#conditionals">Conditionals, Ternaries, and Conditional Assignment</a><br />
<a href="#existence">The Existence Operator</a><br />
<a href="#aliases">Aliases</a><br />
<a href="#splats">Splats</a><br />
<a href="#splats">Splats...</a><br />
<a href="#arguments">Arguments are Arrays</a><br />
<a href="#while">While Loops</a><br />
<a href="#comprehensions">Comprehensions (Arrays, Objects, and Ranges)</a><br />
@@ -108,9 +93,13 @@
<p>
For a longer CoffeeScript example, check out
<a href="documentation/underscore.html">Underscore.coffee</a>, a port
of <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
to CoffeeScript, which, when compiled, can pass the complete Underscore test suite.
Or, clone the source and take a look in the
of the <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
library of helper functions. Underscore.coffee can pass the entire Underscore.js
test suite. The CoffeeScript version is faster than the original for a number
of methods (in general, due to the speed of CoffeeScript's array comprehensions), and
after being minified and gzipped, is only 241 bytes larger than the original
JavaScript version.
Additional examples are included in the source repository, inside the
<a href="http://github.com/jashkenas/coffee-script/tree/master/examples/">examples</a> folder.
</p>
@@ -203,9 +192,15 @@ gem install coffee-script</pre>
<tr>
<td><code>-n, --no-wrap</code></td>
<td>
Compile the JavaScript without the top-level function safety wrapper
or var declarations, for situations where you want to add every
variable to global scope.
Compile the JavaScript without the top-level function safety wrapper.
(Used for CoffeeScript as a Narwhal module.)
</td>
</tr>
<tr>
<td><code>-g, --globals</code></td>
<td>
Suppress all variable declarations at the top-level, effectively adding
those variables to the global scope. (Used by the REPL.)
</td>
</tr>
<tr>
@@ -250,6 +245,13 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
use indentation.
</p>
<p>
You can use newlines to break up your expression into smaller pieces,
as long as CoffeeScript can tell that the line hasn't finished
(similar to how Ruby handles it). For example,
if the line ends in an operator, dot, or keyword.
</p>
<p id="functions">
<b class="header">Functions and Invocation</b>
Functions are defined by a list of parameters, an arrow, and the
@@ -365,10 +367,10 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<%= code_for('aliases') %>
<p id="splats">
<b class="header">Splats</b>
<b class="header">Splats...</b>
The JavaScript <b>arguments object</b> is a useful way to work with
functions that accept variable numbers of arguments. CoffeeScript provides
splats <tt>*</tt>, both for function definition as well as invocation,
splats <tt>...</tt>, both for function definition as well as invocation,
making variable arguments a little bit more palatable.
</p>
<%= code_for('splats', true) %>
@@ -376,8 +378,8 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<p id="arguments">
<b class="header">Arguments are Arrays</b>
If you reference the <b>arguments object</b> directly, it will be converted
into a real Array, making all of the
<a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array">Array methods</a>
into a real Array, making all of the
<a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array">Array methods</a>
available.
</p>
<%= code_for('arguments', true) %>
@@ -407,12 +409,14 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<p>
If you know the start and end of your loop, or would like to step through
in fixed-size increments, you can use a range to specify the start and
end of your comprehension:
end of your comprehension. (The long line-breaking "for" definitions in
the compiled JS below allow ranges to count downwards, as well as upwards).
</p>
<%= code_for('range_comprehensions') %>
<%= code_for('range_comprehensions', 'countdown') %>
<p>
Comprehensions can also be used to iterate over the values and keys in
an object:
Comprehensions can also be used to iterate over the keys and values in
an object. Use <tt>ino</tt> to signal comprehension over an object instead
of an array.
</p>
<%= code_for('object_comprehensions', 'ages.join(", ")') %>
@@ -442,6 +446,11 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
below.
</p>
<%= code_for('expressions', 'eldest') %>
<p>
Even though functions will always return their final value, it's both possible
and encouraged to return early from a function body writing out the explicit
return (<tt>return value</tt>), when you know that you're done.
</p>
<p>
Because variable declarations occur at the top of scope, assignment can
be used within expressions, even for variables that haven't been seen before:
@@ -472,10 +481,13 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
be completely usable if it weren't for a couple of small exceptions:
it's awkward to call <b>super</b> (the prototype object's
implementation of the current function), and it's awkward to correctly
set the prototype chain. CoffeeScript provides <tt>extends</tt>
to help with prototype setup, and converts
<tt>super()</tt> calls into calls against the immediate ancestor's
method of the same name.
set the prototype chain.
</p>
<p>
CoffeeScript provides <tt>extends</tt>
to help with prototype setup, <tt>::</tt> for quick access to an
object's prototype, and converts <tt>super()</tt> into a call against
the immediate ancestor's method of the same name.
</p>
<%= code_for('super', true) %>
@@ -525,12 +537,15 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<ul>
<li>
<a href="http://github.com/jashkenas/coffee-script/">Source Code</a><br />
Use <tt>bin/coffee</tt> to test your changes, or <tt>rake gem:install</tt> to
create and install a custom version of the gem. If you're hacking on the
parser, use <tt>rake build:parser</tt> to rebuild it.
After checking out the source, make sure to run <tt>rake build:parser</tt>
to generate an up-to-date version of the Racc parser.
Use <tt>bin/coffee</tt> to test your changes,
<tt>rake test</tt> to run the test suite,
and <tt>rake gem:install</tt> to
create and install a custom version of the gem.
</li>
<li>
<a href="http://github.com/jashkenas/coffee-script/issues">Bugs and Feature Requests</a>
<a href="http://github.com/jashkenas/coffee-script/issues">Bugs, Feature Requests, and General Discussion</a>
</li>
<li>
<a href="http://github.com/jnicklas/bistro_car">BistroCar</a><br />
@@ -544,19 +559,14 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<h2 id="contributing">Contributing</h2>
<p>
Here's a wish list of things that would be wonderful to have in
CoffeeScript:
Here's a wish list of things that would be wonderful to have contributed:
</p>
<ul>
<li>
A clean, safe syntax for manipulating the prototype chain, and performing
inheritance. <a href="#inheritance"><b>extends</b> and <b>super</b></a> are the start of this, but
aren't a complete answer.
</li>
<li>
A CoffeeScript version of the compiler, perhaps using Alessandro Warth's
<a href="http://tinlizzie.org/ometa/">OMeta</a>.
<a href="http://github.com/jashkenas/coffee-script/issues#issue/8">
A CoffeeScript version of the compiler.
</a>
</li>
<li>
Test cases for any syntax errors you encounter that you think CoffeeScript
@@ -579,6 +589,27 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<h2 id="change_log">Change Log</h2>
<p>
<b class="header" style="margin-top: 20px;">0.2.2</b>
When performing a comprehension over an object, use <tt>ino</tt>, instead
of <tt>in</tt>, which helps us generate smaller, more efficient code at
compile time.
<br />
Added <tt>::</tt> as a shorthand for saying <tt>.prototype.</tt>
<br />
The "splat" symbol has been changed from a prefix asterisk <tt>*</tt>, to
a postfix ellipsis <tt>...</tt>
<br />
Added JavaScript's <tt>in</tt> operator,
empty <tt>return</tt> statements, and empty <tt>while</tt> loops.
<br />
Constructor functions that start with capital letters now include a
safety check to make sure that the new instance of the object is returned.
<br />
The <tt>extends</tt> keyword now functions identically to <tt>goog.inherits</tt>
in Google's Closure Library.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.2.1</b>
Arguments objects are now converted into real arrays when referenced.

View File

@@ -1,32 +1,24 @@
(function(){
var __a, __b, __c, __d, __e, __f, __g, __h, __i, __j, food, lunch, roid, roid2;
var __a, __b, __c, __d, __e, __f, __g, food, lunch, roid, roid2;
// Eat lunch.
lunch = (function() {
__a = ['toast', 'cheese', 'wine'];
__c = [];
for (__b in __a) {
if (__a.hasOwnProperty(__b)) {
food = __a[__b];
__d = eat(food);
__c.push(__d);
}
__c = []; __a = ['toast', 'cheese', 'wine'];
for (__b=0; __b<__a.length; __b++) {
food = __a[__b];
__c.push(eat(food));
}
return __c;
})();
// Naive collision detection.
__e = asteroids;
for (__f in __e) {
if (__e.hasOwnProperty(__f)) {
roid = __e[__f];
__h = asteroids;
for (__i in __h) {
if (__h.hasOwnProperty(__i)) {
roid2 = __h[__i];
if (roid !== roid2) {
if (roid.overlaps(roid2)) {
roid.explode();
}
}
__d = asteroids;
for (__e=0; __e<__d.length; __e++) {
roid = __d[__e];
__f = asteroids;
for (__g=0; __g<__f.length; __g++) {
roid2 = __f[__g];
if (roid !== roid2) {
if (roid.overlaps(roid2)) {
roid.explode();
}
}
}

View File

@@ -1,14 +1,11 @@
(function(){
var __a, __b, __c, globals, name, property;
var __a, __b, globals, name;
// The first ten global properties.
globals = ((function() {
__a = window;
__b = [];
__b = []; __a = window;
for (name in __a) {
if (__a.hasOwnProperty(name)) {
property = __a[name];
__c = name;
__b.push(__c);
__b.push(name);
}
}
return __b;

View File

@@ -3,7 +3,7 @@
try {
return nonexistent / undefined;
} catch (error) {
return "The error is: " + error;
return "Caught an error: " + error;
}
})());
})();

View File

@@ -1,18 +1,16 @@
(function(){
var __a, __b, __c, age, ages, child, years_old;
var __a, __b, age, ages, child, years_old;
years_old = {
max: 10,
ida: 9,
tim: 11
};
ages = (function() {
__a = years_old;
__b = [];
__b = []; __a = years_old;
for (child in __a) {
age = __a[child];
if (__a.hasOwnProperty(child)) {
age = __a[child];
__c = child + " is " + age;
__b.push(__c);
__b.push(child + " is " + age);
}
}
return __b;

View File

@@ -1,5 +1,5 @@
(function(){
var __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, race, square;
var __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
// Assignment:
number = 42;
opposite_day = true;
@@ -33,14 +33,10 @@
}
// Array comprehensions:
cubed_list = (function() {
__a = list;
__c = [];
for (__b in __a) {
if (__a.hasOwnProperty(__b)) {
num = __a[__b];
__d = math.cube(num);
__c.push(__d);
}
__c = []; __a = list;
for (__b=0; __b<__a.length; __b++) {
num = __a[__b];
__c.push(math.cube(num));
}
return __c;
})();

View File

@@ -1,9 +1,21 @@
(function(){
var __a, __b, __c, __d, __e, dozen_eggs, i;
__d = 0;
__e = eggs.length;
for (__c=0, i=__d; (__d <= __e ? i < __e : i > __e); (__d <= __e ? i += 12 : i -= 12), __c++) {
dozen_eggs = eggs.slice(i, i + 12);
deliver(new egg_carton(dozen));
}
var __a, __b, __c, __d, __e, countdown, egg_delivery, num;
countdown = (function() {
__b = []; __d = 10; __e = 1;
for (__c=0, num=__d; (__d <= __e ? num <= __e : num >= __e); (__d <= __e ? num += 1 : num -= 1), __c++) {
__b.push(num);
}
return __b;
})();
egg_delivery = function egg_delivery() {
var __f, __g, __h, __i, __j, dozen_eggs, i;
__g = []; __i = 0; __j = eggs.length;
for (__h=0, i=__i; (__i <= __j ? i < __j : i > __j); (__i <= __j ? i += 12 : i -= 12), __h++) {
__g.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
})());
}
return __g;
};
})();

View File

@@ -1,25 +1,33 @@
(function(){
var Animal, Horse, Snake, sam, tom;
var Animal, Horse, Snake, __a, __b, sam, tom;
Animal = function Animal() {
};
Animal.prototype.move = function move(meters) {
return alert(this.name + " moved " + meters + "m.");
};
Snake = function Snake(name) {
return this.name = name;
var __a;
__a = this.name = name;
return Snake === this.constructor ? this : __a;
};
__a = function(){};
__a.prototype = Animal.prototype;
Snake.__superClass__ = Animal.prototype;
Snake.prototype = new Animal();
Snake.prototype = new __a();
Snake.prototype.constructor = Snake;
Snake.prototype.move = function move() {
alert("Slithering...");
return Snake.__superClass__.move.call(this, 5);
};
Horse = function Horse(name) {
return this.name = name;
var __b;
__b = this.name = name;
return Horse === this.constructor ? this : __b;
};
__b = function(){};
__b.prototype = Animal.prototype;
Horse.__superClass__ = Animal.prototype;
Horse.prototype = new Animal();
Horse.prototype = new __b();
Horse.prototype.constructor = Horse;
Horse.prototype.move = function move() {
alert("Galloping...");

77
documentation/speed.html Normal file
View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Quickie CoffeeScript Speed Tests</title>
<script type="text/javascript" src="http://www.broofa.com/Tools/JSLitmus/JSLitmus.js"></script>
</head>
<body>
<h1>Quickie CoffeeScript Speed Tests</h1>
<script type="text/javascript">
var num = 1000;
var arr = [];
while (num--) arr.push(num);
JSLitmus.test('current comprehensions', function() {
__a = arr;
__c = [];
for (__b in __a) {
if (__a.hasOwnProperty(__b)) {
num = __a[__b];
__d = num;
__c.push(num);
}
}
});
JSLitmus.test('raw for loop (best we can do)', function() {
__a = arr;
__c = new Array(__a.length);
for (__b=0; __b < __a.length; __b++) {
__c[__b] = __a[__b];
}
});
JSLitmus.test('current without hasOwnProperty check', function() {
__a = arr;
__c = [];
for (__b in __a) {
num = __a[__b];
__d = num;
__c.push(num);
}
});
JSLitmus.test('raw for..in loop', function() {
__a = arr;
__c = new Array(__a.length);
for (__b in __a) {
__c[__b] = __a[__b];
}
});
JSLitmus.test('weepy\'s comprehensions', function() {
__c = []; __a = arr;
__d = function(num, __b) {
__c.push(num);
};
if (__a instanceof Array) {
for (__b=0; __b<__a.length; __b++) __d(__a[__b], __b);
} else {
for (__b in __a) { if (__a.hasOwnProperty(__b)) __d(__a[__b], __b); }
}
});
JSLitmus.test('CoffeeScript 0.2.2 comprehensions', function() {
__c = []; __a = arr;
for (__b=0; __b<__a.length; __b++) {
num = __a[__b];
__c.push(num);
}
});
</script>
</body>
</html>

View File

@@ -14,7 +14,6 @@
font-size: 12px;
}
</style>
</head>
<body>
@@ -31,56 +30,56 @@
<span class="line-numbers"> 11 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Baseline setup ---------------------------------</span>
<span class="line-numbers"> 12 </span>
<span class="line-numbers"> 13 </span> <span class="Comment"><span class="Comment">#</span> Establish the root object, &quot;window&quot; in the browser, or &quot;global&quot; on the server.</span>
<span class="line-numbers"> 14 </span> root<span class="Keyword">:</span> <span class="Variable">this</span>
<span class="line-numbers"> 14 </span> <span class="FunctionName">root</span><span class="Keyword">:</span> <span class="Variable">this</span>
<span class="line-numbers"> 15 </span>
<span class="line-numbers"> 16 </span>
<span class="line-numbers"> 17 </span> <span class="Comment"><span class="Comment">#</span> Save the previous value of the &quot;_&quot; variable.</span>
<span class="line-numbers"> 18 </span> previousUnderscore<span class="Keyword">:</span> root._
<span class="line-numbers"> 18 </span> <span class="FunctionName">previousUnderscore</span><span class="Keyword">:</span> root._
<span class="line-numbers"> 19 </span>
<span class="line-numbers"> 20 </span>
<span class="line-numbers"> 21 </span> <span class="Comment"><span class="Comment">#</span> If Underscore is called as a function, it returns a wrapped object that</span>
<span class="line-numbers"> 22 </span> <span class="Comment"><span class="Comment">#</span> can be used OO-style. This wrapper holds altered versions of all the</span>
<span class="line-numbers"> 23 </span> <span class="Comment"><span class="Comment">#</span> underscore functions. Wrapped objects may be chained.</span>
<span class="line-numbers"> 24 </span> <span class="FunctionName">wrapper</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 25 </span> <span class="Variable">this</span>._wrapped<span class="Keyword">:</span> obj
<span class="line-numbers"> 24 </span> <span class="FunctionArgument"> wrapper: obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 25 </span> <span class="Variable">this</span>.<span class="FunctionName">_wrapped</span><span class="Keyword">:</span> obj
<span class="line-numbers"> 26 </span> <span class="Variable">this</span>
<span class="line-numbers"> 27 </span>
<span class="line-numbers"> 28 </span>
<span class="line-numbers"> 29 </span> <span class="Comment"><span class="Comment">#</span> Establish the object that gets thrown to break out of a loop iteration.</span>
<span class="line-numbers"> 30 </span> breaker<span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(StopIteration) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>__break__<span class="String">'</span></span> <span class="Keyword">else</span> StopIteration
<span class="line-numbers"> 30 </span> <span class="FunctionName">breaker</span><span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(StopIteration) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>__break__<span class="String">'</span></span> <span class="Keyword">else</span> StopIteration
<span class="line-numbers"> 31 </span>
<span class="line-numbers"> 32 </span>
<span class="line-numbers"> 33 </span> <span class="Comment"><span class="Comment">#</span> Create a safe reference to the Underscore object for reference below.</span>
<span class="line-numbers"> 34 </span> _<span class="Keyword">:</span> <span class="FunctionName">root._</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">new</span> <span class="TypeName">wrapper</span>(obj)
<span class="line-numbers"> 33 </span> <span class="Comment"><span class="Comment">#</span> Create a safe reference to the Underscore object forreference below.</span>
<span class="line-numbers"> 34 </span> <span class="FunctionArgument"> _: root._: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">new</span> <span class="TypeName">wrapper</span>(obj)
<span class="line-numbers"> 35 </span>
<span class="line-numbers"> 36 </span>
<span class="line-numbers"> 37 </span> <span class="Comment"><span class="Comment">#</span> Export the Underscore object for CommonJS.</span>
<span class="line-numbers"> 38 </span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(exports) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> exports._<span class="Keyword">:</span> _
<span class="line-numbers"> 38 </span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(exports) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> exports.<span class="FunctionName">_</span><span class="Keyword">:</span> _
<span class="line-numbers"> 39 </span>
<span class="line-numbers"> 40 </span>
<span class="line-numbers"> 41 </span> <span class="Comment"><span class="Comment">#</span> Create quick reference variables for speed access to core prototypes.</span>
<span class="line-numbers"> 42 </span> slice<span class="Keyword">:</span> Array.prototype.slice
<span class="line-numbers"> 43 </span> unshift<span class="Keyword">:</span> Array.prototype.unshift
<span class="line-numbers"> 44 </span> toString<span class="Keyword">:</span> Object.prototype.toString
<span class="line-numbers"> 45 </span> hasOwnProperty<span class="Keyword">:</span> Object.prototype.hasOwnProperty
<span class="line-numbers"> 46 </span> propertyIsEnumerable<span class="Keyword">:</span> Object.prototype.propertyIsEnumerable
<span class="line-numbers"> 42 </span> <span class="FunctionName">slice</span><span class="Keyword">:</span> Array<span class="Keyword">:</span><span class="Keyword">:</span>slice
<span class="line-numbers"> 43 </span> <span class="FunctionName">unshift</span><span class="Keyword">:</span> Array<span class="Keyword">:</span><span class="Keyword">:</span>unshift
<span class="line-numbers"> 44 </span> <span class="FunctionName">toString</span><span class="Keyword">:</span> Object<span class="Keyword">:</span><span class="Keyword">:</span>toString
<span class="line-numbers"> 45 </span> <span class="FunctionName">hasOwnProperty</span><span class="Keyword">:</span> Object<span class="Keyword">:</span><span class="Keyword">:</span>hasOwnProperty
<span class="line-numbers"> 46 </span> <span class="FunctionName">propertyIsEnumerable</span><span class="Keyword">:</span> Object<span class="Keyword">:</span><span class="Keyword">:</span>propertyIsEnumerable
<span class="line-numbers"> 47 </span>
<span class="line-numbers"> 48 </span>
<span class="line-numbers"> 49 </span> <span class="Comment"><span class="Comment">#</span> Current version.</span>
<span class="line-numbers"> 50 </span> _.VERSION<span class="Keyword">:</span> <span class="String"><span class="String">'</span>0.5.3<span class="String">'</span></span>
<span class="line-numbers"> 50 </span> _.<span class="FunctionName">VERSION</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>0.5.5<span class="String">'</span></span>
<span class="line-numbers"> 51 </span>
<span class="line-numbers"> 52 </span>
<span class="line-numbers"> 53 </span> <span class="Comment"><span class="Comment">#</span> ------------------------ Collection Functions: ---------------------------</span>
<span class="line-numbers"> 54 </span>
<span class="line-numbers"> 55 </span> <span class="Comment"><span class="Comment">#</span> The cornerstone, an each implementation.</span>
<span class="line-numbers"> 56 </span> <span class="Comment"><span class="Comment">#</span> Handles objects implementing forEach, arrays, and raw objects.</span>
<span class="line-numbers"> 57 </span> <span class="FunctionName">_.each</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 58 </span> index<span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 57 </span> <span class="FunctionArgument"> _.each: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 58 </span> <span class="FunctionName">index</span><span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 59 </span> <span class="Keyword">try</span>
<span class="line-numbers"> 60 </span> <span class="Keyword">return</span> obj.forEach(iterator, context) <span class="Keyword">if</span> obj.forEach
<span class="line-numbers"> 61 </span> <span class="Keyword">if</span> _.isArray(obj) <span class="Keyword">or</span> _.isArguments(obj)
<span class="line-numbers"> 62 </span> <span class="Keyword">return</span> iterator.call(context, obj[i], i, obj) <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...obj.length]
<span class="line-numbers"> 63 </span> iterator.call(context, val, key, obj) <span class="Keyword">for</span> val, key <span class="Keyword">in</span> obj
<span class="line-numbers"> 63 </span> iterator.call(context, val, key, obj) <span class="Keyword">for</span> key, val <span class="Keyword">ino</span> obj
<span class="line-numbers"> 64 </span> <span class="Keyword">catch</span> e
<span class="line-numbers"> 65 </span> <span class="Keyword">throw</span> e <span class="Keyword">if</span> e <span class="Keyword">isnt</span> breaker
<span class="line-numbers"> 66 </span> obj
@@ -88,9 +87,9 @@
<span class="line-numbers"> 68 </span>
<span class="line-numbers"> 69 </span> <span class="Comment"><span class="Comment">#</span> Return the results of applying the iterator to each element. Use JavaScript</span>
<span class="line-numbers"> 70 </span> <span class="Comment"><span class="Comment">#</span> 1.6's version of map, if possible.</span>
<span class="line-numbers"> 71 </span> <span class="FunctionName">_.map</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 71 </span> <span class="FunctionArgument"> _.map: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 72 </span> <span class="Keyword">return</span> obj.map(iterator, context) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.map))
<span class="line-numbers"> 73 </span> results<span class="Keyword">:</span> []
<span class="line-numbers"> 73 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
<span class="line-numbers"> 74 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 75 </span> results.push(iterator.call(context, value, index, list))
<span class="line-numbers"> 76 </span> results
@@ -98,45 +97,45 @@
<span class="line-numbers"> 78 </span>
<span class="line-numbers"> 79 </span> <span class="Comment"><span class="Comment">#</span> Reduce builds up a single result from a list of values. Also known as</span>
<span class="line-numbers"> 80 </span> <span class="Comment"><span class="Comment">#</span> inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.</span>
<span class="line-numbers"> 81 </span> <span class="FunctionName">_.reduce</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, memo, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 81 </span> <span class="FunctionArgument"> _.reduce: obj, memo, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 82 </span> <span class="Keyword">return</span> obj.reduce(_.bind(iterator, context), memo) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.reduce))
<span class="line-numbers"> 83 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 84 </span> memo<span class="Keyword">:</span> iterator.call(context, memo, value, index, list)
<span class="line-numbers"> 84 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call(context, memo, value, index, list)
<span class="line-numbers"> 85 </span> memo
<span class="line-numbers"> 86 </span>
<span class="line-numbers"> 87 </span>
<span class="line-numbers"> 88 </span> <span class="Comment"><span class="Comment">#</span> The right-associative version of reduce, also known as foldr. Uses</span>
<span class="line-numbers"> 89 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.8's version of reduceRight, if available.</span>
<span class="line-numbers"> 90 </span> <span class="FunctionName">_.reduceRight</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, memo, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 90 </span> <span class="FunctionArgument"> _.reduceRight: obj, memo, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 91 </span> <span class="Keyword">return</span> obj.reduceRight(_.bind(iterator, context), memo) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.reduceRight))
<span class="line-numbers"> 92 </span> _.each(_.clone(_.toArray(obj)).reverse())<span class="FunctionArgument"> value, index </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 93 </span> memo<span class="Keyword">:</span> iterator.call(context, memo, value, index, obj)
<span class="line-numbers"> 93 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call(context, memo, value, index, obj)
<span class="line-numbers"> 94 </span> memo
<span class="line-numbers"> 95 </span>
<span class="line-numbers"> 96 </span>
<span class="line-numbers"> 97 </span> <span class="Comment"><span class="Comment">#</span> Return the first value which passes a truth test.</span>
<span class="line-numbers"> 98 </span> <span class="FunctionName">_.detect</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 99 </span> result<span class="Keyword">:</span> <span class="BuiltInConstant">null</span>
<span class="line-numbers"> 98 </span> <span class="FunctionArgument"> _.detect: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 99 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">null</span>
<span class="line-numbers"> 100 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 101 </span> <span class="Keyword">if</span> iterator.call(context, value, index, list)
<span class="line-numbers"> 102 </span> result<span class="Keyword">:</span> value
<span class="line-numbers"> 102 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> value
<span class="line-numbers"> 103 </span> _.breakLoop()
<span class="line-numbers"> 104 </span> result
<span class="line-numbers"> 105 </span>
<span class="line-numbers"> 106 </span>
<span class="line-numbers"> 107 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements that pass a truth test. Use JavaScript 1.6's</span>
<span class="line-numbers"> 108 </span> <span class="Comment"><span class="Comment">#</span> filter(), if it exists.</span>
<span class="line-numbers"> 109 </span> <span class="FunctionName">_.select</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 109 </span> <span class="FunctionArgument"> _.select: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 110 </span> <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.filter) <span class="Keyword">then</span> <span class="Keyword">return</span> obj.filter(iterator, context)
<span class="line-numbers"> 111 </span> results<span class="Keyword">:</span> []
<span class="line-numbers"> 111 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
<span class="line-numbers"> 112 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 113 </span> results.push(value) <span class="Keyword">if</span> iterator.call(context, value, index, list)
<span class="line-numbers"> 114 </span> results
<span class="line-numbers"> 115 </span>
<span class="line-numbers"> 116 </span>
<span class="line-numbers"> 117 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements for which a truth test fails.</span>
<span class="line-numbers"> 118 </span> <span class="FunctionName">_.reject</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 119 </span> results<span class="Keyword">:</span> []
<span class="line-numbers"> 118 </span> <span class="FunctionArgument"> _.reject: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 119 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
<span class="line-numbers"> 120 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 121 </span> results.push(value) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator.call(context, value, index, list)
<span class="line-numbers"> 122 </span> results
@@ -144,89 +143,89 @@
<span class="line-numbers"> 124 </span>
<span class="line-numbers"> 125 </span> <span class="Comment"><span class="Comment">#</span> Determine whether all of the elements match a truth test. Delegate to</span>
<span class="line-numbers"> 126 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's every(), if it is present.</span>
<span class="line-numbers"> 127 </span> <span class="FunctionName">_.all</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 127 </span> <span class="FunctionArgument"> _.all: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 128 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
<span class="line-numbers"> 129 </span> <span class="Keyword">return</span> obj.every(iterator, context) <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.every)
<span class="line-numbers"> 130 </span> result<span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 130 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 131 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 132 </span> _.breakLoop() <span class="Keyword">unless</span> (result<span class="Keyword">:</span> result <span class="Keyword">and</span> iterator.call(context, value, index, list))
<span class="line-numbers"> 132 </span> _.breakLoop() <span class="Keyword">unless</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> result <span class="Keyword">and</span> iterator.call(context, value, index, list))
<span class="line-numbers"> 133 </span> result
<span class="line-numbers"> 134 </span>
<span class="line-numbers"> 135 </span>
<span class="line-numbers"> 136 </span> <span class="Comment"><span class="Comment">#</span> Determine if at least one element in the object matches a truth test. Use</span>
<span class="line-numbers"> 137 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's some(), if it exists.</span>
<span class="line-numbers"> 138 </span> <span class="FunctionName">_.any</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 138 </span> <span class="FunctionArgument"> _.any: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 139 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
<span class="line-numbers"> 140 </span> <span class="Keyword">return</span> obj.some(iterator, context) <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.some)
<span class="line-numbers"> 141 </span> result<span class="Keyword">:</span> <span class="BuiltInConstant">false</span>
<span class="line-numbers"> 141 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">false</span>
<span class="line-numbers"> 142 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 143 </span> _.breakLoop() <span class="Keyword">if</span> (result<span class="Keyword">:</span> iterator.call(context, value, index, list))
<span class="line-numbers"> 143 </span> _.breakLoop() <span class="Keyword">if</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> iterator.call(context, value, index, list))
<span class="line-numbers"> 144 </span> result
<span class="line-numbers"> 145 </span>
<span class="line-numbers"> 146 </span>
<span class="line-numbers"> 147 </span> <span class="Comment"><span class="Comment">#</span> Determine if a given value is included in the array or object,</span>
<span class="line-numbers"> 148 </span> <span class="Comment"><span class="Comment">#</span> based on '==='.</span>
<span class="line-numbers"> 149 </span> <span class="FunctionName">_.include</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, target</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 149 </span> <span class="FunctionArgument"> _.include: obj, target </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 150 </span> <span class="Keyword">return</span> _.indexOf(obj, target) <span class="Keyword">isnt</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">if</span> _.isArray(obj)
<span class="line-numbers"> 151 </span> <span class="Keyword">for</span> val <span class="Keyword">in</span> obj
<span class="line-numbers"> 151 </span> <span class="Keyword">for</span> key, val <span class="Keyword">ino</span> obj
<span class="line-numbers"> 152 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> val <span class="Keyword">is</span> target
<span class="line-numbers"> 153 </span> <span class="BuiltInConstant">false</span>
<span class="line-numbers"> 154 </span>
<span class="line-numbers"> 155 </span>
<span class="line-numbers"> 156 </span> <span class="Comment"><span class="Comment">#</span> Invoke a method with arguments on every item in a collection.</span>
<span class="line-numbers"> 157 </span> <span class="FunctionName">_.invoke</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, method</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 158 </span> args<span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 157 </span> <span class="FunctionArgument"> _.invoke: obj, method </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 158 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 159 </span> (<span class="Keyword">if</span> method <span class="Keyword">then</span> val[method] <span class="Keyword">else</span> val).apply(val, args) <span class="Keyword">for</span> val <span class="Keyword">in</span> obj
<span class="line-numbers"> 160 </span>
<span class="line-numbers"> 161 </span>
<span class="line-numbers"> 162 </span> <span class="Comment"><span class="Comment">#</span> Convenience version of a common use case of map: fetching a property.</span>
<span class="line-numbers"> 163 </span> <span class="FunctionName">_.pluck</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, key</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 163 </span> <span class="FunctionArgument"> _.pluck: obj, key </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 164 </span> _.map(obj, (<span class="FunctionArgument">val </span><span class="Storage">=&gt;</span> val[key]))
<span class="line-numbers"> 165 </span>
<span class="line-numbers"> 166 </span>
<span class="line-numbers"> 167 </span> <span class="Comment"><span class="Comment">#</span> Return the maximum item or (item-based computation).</span>
<span class="line-numbers"> 168 </span> <span class="FunctionName">_.max</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 168 </span> <span class="FunctionArgument"> _.max: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 169 </span> <span class="Keyword">return</span> Math.max.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
<span class="line-numbers"> 170 </span> result<span class="Keyword">:</span> {computed<span class="Keyword">:</span> <span class="Keyword">-</span><span class="BuiltInConstant">Infinity</span>}
<span class="line-numbers"> 170 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="BuiltInConstant">Infinity</span>}
<span class="line-numbers"> 171 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 172 </span> computed<span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
<span class="line-numbers"> 173 </span> computed <span class="Keyword">&gt;=</span> result.computed <span class="Keyword">and</span> (result<span class="Keyword">:</span> {value<span class="Keyword">:</span> value, computed<span class="Keyword">:</span> computed})
<span class="line-numbers"> 172 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
<span class="line-numbers"> 173 </span> computed <span class="Keyword">&gt;=</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
<span class="line-numbers"> 174 </span> result.value
<span class="line-numbers"> 175 </span>
<span class="line-numbers"> 176 </span>
<span class="line-numbers"> 177 </span> <span class="Comment"><span class="Comment">#</span> Return the minimum element (or element-based computation).</span>
<span class="line-numbers"> 178 </span> <span class="FunctionName">_.min</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 178 </span> <span class="FunctionArgument"> _.min: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 179 </span> <span class="Keyword">return</span> Math.min.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
<span class="line-numbers"> 180 </span> result<span class="Keyword">:</span> {computed<span class="Keyword">:</span> <span class="BuiltInConstant">Infinity</span>}
<span class="line-numbers"> 180 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="BuiltInConstant">Infinity</span>}
<span class="line-numbers"> 181 </span> _.each(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 182 </span> computed<span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
<span class="line-numbers"> 183 </span> computed <span class="Keyword">&lt;</span> result.computed <span class="Keyword">and</span> (result<span class="Keyword">:</span> {value<span class="Keyword">:</span> value, computed<span class="Keyword">:</span> computed})
<span class="line-numbers"> 182 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
<span class="line-numbers"> 183 </span> computed <span class="Keyword">&lt;</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
<span class="line-numbers"> 184 </span> result.value
<span class="line-numbers"> 185 </span>
<span class="line-numbers"> 186 </span>
<span class="line-numbers"> 187 </span> <span class="Comment"><span class="Comment">#</span> Sort the object's values by a criteria produced by an iterator.</span>
<span class="line-numbers"> 188 </span> <span class="FunctionName">_.sortBy</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, iterator, context</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 188 </span> <span class="FunctionArgument"> _.sortBy: obj, iterator, context </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 189 </span> _.pluck(((_.map(obj)<span class="FunctionArgument"> value, index, list </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 190 </span> {value<span class="Keyword">:</span> value, criteria<span class="Keyword">:</span> iterator.call(context, value, index, list)}
<span class="line-numbers"> 190 </span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">criteria</span><span class="Keyword">:</span> iterator.call(context, value, index, list)}
<span class="line-numbers"> 191 </span> ).sort()<span class="FunctionArgument"> left, right </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 192 </span> a<span class="Keyword">:</span> left.criteria; b<span class="Keyword">:</span> right.criteria
<span class="line-numbers"> 192 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> left.criteria; <span class="FunctionName">b</span><span class="Keyword">:</span> right.criteria
<span class="line-numbers"> 193 </span> <span class="Keyword">if</span> a <span class="Keyword">&lt;</span> b <span class="Keyword">then</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">else</span> <span class="Keyword">if</span> a <span class="Keyword">&gt;</span> b <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="Number">0</span>
<span class="line-numbers"> 194 </span> ), <span class="String"><span class="String">'</span>value<span class="String">'</span></span>)
<span class="line-numbers"> 195 </span>
<span class="line-numbers"> 196 </span>
<span class="line-numbers"> 197 </span> <span class="Comment"><span class="Comment">#</span> Use a comparator function to figure out at what index an object should</span>
<span class="line-numbers"> 198 </span> <span class="Comment"><span class="Comment">#</span> be inserted so as to maintain order. Uses binary search.</span>
<span class="line-numbers"> 199 </span> <span class="FunctionName">_.sortedIndex</span><span class="Keyword">:</span> <span class="FunctionArgument">array, obj, iterator</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 199 </span> <span class="FunctionArgument"> _.sortedIndex: array, obj, iterator </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 200 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
<span class="line-numbers"> 201 </span> low<span class="Keyword">:</span> <span class="Number">0</span>; high<span class="Keyword">:</span> array.length
<span class="line-numbers"> 201 </span> <span class="FunctionName">low</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">high</span><span class="Keyword">:</span> array.length
<span class="line-numbers"> 202 </span> <span class="Keyword">while</span> low <span class="Keyword">&lt;</span> high
<span class="line-numbers"> 203 </span> mid<span class="Keyword">:</span> (low <span class="Keyword">+</span> high) <span class="Keyword">&gt;</span><span class="Keyword">&gt;</span> <span class="Number">1</span>
<span class="line-numbers"> 204 </span> <span class="Keyword">if</span> iterator(array[mid]) <span class="Keyword">&lt;</span> iterator(obj) <span class="Keyword">then</span> low<span class="Keyword">:</span> mid <span class="Keyword">+</span> <span class="Number">1</span> <span class="Keyword">else</span> high<span class="Keyword">:</span> mid
<span class="line-numbers"> 203 </span> <span class="FunctionName">mid</span><span class="Keyword">:</span> (low <span class="Keyword">+</span> high) <span class="Keyword">&gt;</span><span class="Keyword">&gt;</span> <span class="Number">1</span>
<span class="line-numbers"> 204 </span> <span class="Keyword">if</span> iterator(array[mid]) <span class="Keyword">&lt;</span> iterator(obj) <span class="Keyword">then</span> <span class="FunctionName">low</span><span class="Keyword">:</span> mid <span class="Keyword">+</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="FunctionName">high</span><span class="Keyword">:</span> mid
<span class="line-numbers"> 205 </span> low
<span class="line-numbers"> 206 </span>
<span class="line-numbers"> 207 </span>
<span class="line-numbers"> 208 </span> <span class="Comment"><span class="Comment">#</span> Convert anything iterable into a real, live array.</span>
<span class="line-numbers"> 209 </span> <span class="FunctionName">_.toArray</span><span class="Keyword">:</span> <span class="FunctionArgument">iterable</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 209 </span> <span class="FunctionArgument"> _.toArray: iterable </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 210 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> (<span class="Keyword">!</span>iterable)
<span class="line-numbers"> 211 </span> <span class="Keyword">return</span> iterable.toArray() <span class="Keyword">if</span> (iterable.toArray)
<span class="line-numbers"> 212 </span> <span class="Keyword">return</span> iterable <span class="Keyword">if</span> (_.isArray(iterable))
@@ -235,7 +234,7 @@
<span class="line-numbers"> 215 </span>
<span class="line-numbers"> 216 </span>
<span class="line-numbers"> 217 </span> <span class="Comment"><span class="Comment">#</span> Return the number of elements in an object.</span>
<span class="line-numbers"> 218 </span> <span class="FunctionName">_.size</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> _.toArray(obj).length
<span class="line-numbers"> 218 </span> <span class="FunctionArgument"> _.size: obj </span><span class="Storage">=&gt;</span> _.toArray(obj).length
<span class="line-numbers"> 219 </span>
<span class="line-numbers"> 220 </span>
<span class="line-numbers"> 221 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Array Functions: ------------------------------</span>
@@ -243,7 +242,7 @@
<span class="line-numbers"> 223 </span> <span class="Comment"><span class="Comment">#</span> Get the first element of an array. Passing &quot;n&quot; will return the first N</span>
<span class="line-numbers"> 224 </span> <span class="Comment"><span class="Comment">#</span> values in the array. Aliased as &quot;head&quot;. The &quot;guard&quot; check allows it to work</span>
<span class="line-numbers"> 225 </span> <span class="Comment"><span class="Comment">#</span> with _.map.</span>
<span class="line-numbers"> 226 </span> <span class="FunctionName">_.first</span><span class="Keyword">:</span> <span class="FunctionArgument">array, n, guard</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 226 </span> <span class="FunctionArgument"> _.first: array, n, guard </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 227 </span> <span class="Keyword">if</span> n <span class="Keyword">and</span> <span class="Keyword">not</span> guard <span class="Keyword">then</span> slice.call(array, <span class="Number">0</span>, n) <span class="Keyword">else</span> array[<span class="Number">0</span>]
<span class="line-numbers"> 228 </span>
<span class="line-numbers"> 229 </span>
@@ -251,20 +250,20 @@
<span class="line-numbers"> 231 </span> <span class="Comment"><span class="Comment">#</span> Especially useful on the arguments object. Passing an &quot;index&quot; will return</span>
<span class="line-numbers"> 232 </span> <span class="Comment"><span class="Comment">#</span> the rest of the values in the array from that index onward. The &quot;guard&quot;</span>
<span class="line-numbers"> 233 </span> <span class="Comment"><span class="Comment">#</span> check allows it to work with _.map.</span>
<span class="line-numbers"> 234 </span> <span class="FunctionName">_.rest</span><span class="Keyword">:</span> <span class="FunctionArgument">array, index, guard</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 234 </span> <span class="FunctionArgument"> _.rest: array, index, guard </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 235 </span> slice.call(array, <span class="Keyword">if</span> _.isUndefined(index) <span class="Keyword">or</span> guard <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> index)
<span class="line-numbers"> 236 </span>
<span class="line-numbers"> 237 </span>
<span class="line-numbers"> 238 </span> <span class="Comment"><span class="Comment">#</span> Get the last element of an array.</span>
<span class="line-numbers"> 239 </span> <span class="FunctionName">_.last</span><span class="Keyword">:</span> <span class="FunctionArgument">array</span> <span class="Storage">=&gt;</span> array[array.length <span class="Keyword">-</span> <span class="Number">1</span>]
<span class="line-numbers"> 239 </span> <span class="FunctionArgument"> _.last: array </span><span class="Storage">=&gt;</span> array[array.length <span class="Keyword">-</span> <span class="Number">1</span>]
<span class="line-numbers"> 240 </span>
<span class="line-numbers"> 241 </span>
<span class="line-numbers"> 242 </span> <span class="Comment"><span class="Comment">#</span> Trim out all falsy values from an array.</span>
<span class="line-numbers"> 243 </span> <span class="FunctionName">_.compact</span><span class="Keyword">:</span> <span class="FunctionArgument">array</span> <span class="Storage">=&gt;</span> array[i] <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...array.length] <span class="Keyword">when</span> array[i]
<span class="line-numbers"> 243 </span> <span class="FunctionArgument"> _.compact: array </span><span class="Storage">=&gt;</span> array[i] <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...array.length] <span class="Keyword">when</span> array[i]
<span class="line-numbers"> 244 </span>
<span class="line-numbers"> 245 </span>
<span class="line-numbers"> 246 </span> <span class="Comment"><span class="Comment">#</span> Return a completely flattened version of an array.</span>
<span class="line-numbers"> 247 </span> <span class="FunctionName">_.flatten</span><span class="Keyword">:</span> <span class="FunctionArgument">array</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 247 </span> <span class="FunctionArgument"> _.flatten: array </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 248 </span> _.reduce(array, [])<span class="FunctionArgument"> memo, value </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 249 </span> <span class="Keyword">return</span> memo.concat(_.flatten(value)) <span class="Keyword">if</span> _.isArray(value)
<span class="line-numbers"> 250 </span> memo.push(value)
@@ -272,15 +271,15 @@
<span class="line-numbers"> 252 </span>
<span class="line-numbers"> 253 </span>
<span class="line-numbers"> 254 </span> <span class="Comment"><span class="Comment">#</span> Return a version of the array that does not contain the specified value(s).</span>
<span class="line-numbers"> 255 </span> <span class="FunctionName">_.without</span><span class="Keyword">:</span> <span class="FunctionArgument">array</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 256 </span> values<span class="Keyword">:</span> _.rest(arguments)
<span class="line-numbers"> 255 </span> <span class="FunctionArgument"> _.without: array </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 256 </span> <span class="FunctionName">values</span><span class="Keyword">:</span> _.rest(arguments)
<span class="line-numbers"> 257 </span> val <span class="Keyword">for</span> val <span class="Keyword">in</span> _.toArray(array) <span class="Keyword">when</span> <span class="Keyword">not</span> _.include(values, val)
<span class="line-numbers"> 258 </span>
<span class="line-numbers"> 259 </span>
<span class="line-numbers"> 260 </span> <span class="Comment"><span class="Comment">#</span> Produce a duplicate-free version of the array. If the array has already</span>
<span class="line-numbers"> 261 </span> <span class="Comment"><span class="Comment">#</span> been sorted, you have the option of using a faster algorithm.</span>
<span class="line-numbers"> 262 </span> <span class="FunctionName">_.uniq</span><span class="Keyword">:</span> <span class="FunctionArgument">array, isSorted</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 263 </span> memo<span class="Keyword">:</span> []
<span class="line-numbers"> 262 </span> <span class="FunctionArgument"> _.uniq: array, isSorted </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 263 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> []
<span class="line-numbers"> 264 </span> <span class="Keyword">for</span> el, i <span class="Keyword">in</span> _.toArray(array)
<span class="line-numbers"> 265 </span> memo.push(el) <span class="Keyword">if</span> i <span class="Keyword">is</span> <span class="Number">0</span> <span class="Keyword">||</span> (<span class="Keyword">if</span> isSorted <span class="Keyword">is</span> <span class="BuiltInConstant">true</span> <span class="Keyword">then</span> _.last(memo) <span class="Keyword">isnt</span> el <span class="Keyword">else</span> <span class="Keyword">not</span> _.include(memo, el))
<span class="line-numbers"> 266 </span> memo
@@ -288,8 +287,8 @@
<span class="line-numbers"> 268 </span>
<span class="line-numbers"> 269 </span> <span class="Comment"><span class="Comment">#</span> Produce an array that contains every item shared between all the</span>
<span class="line-numbers"> 270 </span> <span class="Comment"><span class="Comment">#</span> passed-in arrays.</span>
<span class="line-numbers"> 271 </span> <span class="FunctionName">_.intersect</span><span class="Keyword">:</span> <span class="FunctionArgument">array</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 272 </span> rest<span class="Keyword">:</span> _.rest(arguments)
<span class="line-numbers"> 271 </span> <span class="FunctionArgument"> _.intersect: array </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 272 </span> <span class="FunctionName">rest</span><span class="Keyword">:</span> _.rest(arguments)
<span class="line-numbers"> 273 </span> _.select(_.uniq(array))<span class="FunctionArgument"> item </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 274 </span> _.all(rest)<span class="FunctionArgument"> other </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 275 </span> _.indexOf(other, item) <span class="Keyword">&gt;=</span> <span class="Number">0</span>
@@ -297,10 +296,10 @@
<span class="line-numbers"> 277 </span>
<span class="line-numbers"> 278 </span> <span class="Comment"><span class="Comment">#</span> Zip together multiple lists into a single array -- elements that share</span>
<span class="line-numbers"> 279 </span> <span class="Comment"><span class="Comment">#</span> an index go together.</span>
<span class="line-numbers"> 280 </span> <span class="FunctionName">_.zip</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 281 </span> args<span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 282 </span> length<span class="Keyword">:</span> _.max(_.pluck(args, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>))
<span class="line-numbers"> 283 </span> results<span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(length)
<span class="line-numbers"> 280 </span> <span class="FunctionArgument"> _.zip: </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 281 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 282 </span> <span class="FunctionName">length</span><span class="Keyword">:</span> _.max(_.pluck(args, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>))
<span class="line-numbers"> 283 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(length)
<span class="line-numbers"> 284 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...length]
<span class="line-numbers"> 285 </span> results[i]<span class="Keyword">:</span> _.pluck(args, String(i))
<span class="line-numbers"> 286 </span> results
@@ -309,9 +308,9 @@
<span class="line-numbers"> 289 </span> <span class="Comment"><span class="Comment">#</span> If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),</span>
<span class="line-numbers"> 290 </span> <span class="Comment"><span class="Comment">#</span> we need this function. Return the position of the first occurence of an</span>
<span class="line-numbers"> 291 </span> <span class="Comment"><span class="Comment">#</span> item in an array, or -1 if the item is not included in the array.</span>
<span class="line-numbers"> 292 </span> <span class="FunctionName">_.indexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">array, item</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 292 </span> <span class="FunctionArgument"> _.indexOf: array, item </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 293 </span> <span class="Keyword">return</span> array.indexOf(item) <span class="Keyword">if</span> array.indexOf
<span class="line-numbers"> 294 </span> i<span class="Keyword">:</span> <span class="Number">0</span>; l<span class="Keyword">:</span> array.length
<span class="line-numbers"> 294 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">l</span><span class="Keyword">:</span> array.length
<span class="line-numbers"> 295 </span> <span class="Keyword">while</span> l <span class="Keyword">-</span> i
<span class="line-numbers"> 296 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">++</span>
<span class="line-numbers"> 297 </span> <span class="Keyword">-</span><span class="Number">1</span>
@@ -319,9 +318,9 @@
<span class="line-numbers"> 299 </span>
<span class="line-numbers"> 300 </span> <span class="Comment"><span class="Comment">#</span> Provide JavaScript 1.6's lastIndexOf, delegating to the native function,</span>
<span class="line-numbers"> 301 </span> <span class="Comment"><span class="Comment">#</span> if possible.</span>
<span class="line-numbers"> 302 </span> <span class="FunctionName">_.lastIndexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">array, item</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 302 </span> <span class="FunctionArgument"> _.lastIndexOf: array, item </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 303 </span> <span class="Keyword">return</span> array.lastIndexOf(item) <span class="Keyword">if</span> array.lastIndexOf
<span class="line-numbers"> 304 </span> i<span class="Keyword">:</span> array.length
<span class="line-numbers"> 304 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> array.length
<span class="line-numbers"> 305 </span> <span class="Keyword">while</span> i
<span class="line-numbers"> 306 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">--</span>
<span class="line-numbers"> 307 </span> <span class="Keyword">-</span><span class="Number">1</span>
@@ -330,16 +329,16 @@
<span class="line-numbers"> 310 </span> <span class="Comment"><span class="Comment">#</span> Generate an integer Array containing an arithmetic progression. A port of</span>
<span class="line-numbers"> 311 </span> <span class="Comment"><span class="Comment">#</span> the native Python range() function. See:</span>
<span class="line-numbers"> 312 </span> <span class="Comment"><span class="Comment">#</span> http://docs.python.org/library/functions.html#range</span>
<span class="line-numbers"> 313 </span> <span class="FunctionName">_.range</span><span class="Keyword">:</span> <span class="FunctionArgument">start, stop, step</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 314 </span> a<span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 315 </span> solo<span class="Keyword">:</span> a.length <span class="Keyword">&lt;=</span> <span class="Number">1</span>
<span class="line-numbers"> 316 </span> i<span class="Keyword">:</span> start<span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> <span class="Number">0</span> <span class="Keyword">else</span> a[<span class="Number">0</span>];
<span class="line-numbers"> 317 </span> stop<span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> a[<span class="Number">0</span>] <span class="Keyword">else</span> a[<span class="Number">1</span>];
<span class="line-numbers"> 318 </span> step<span class="Keyword">:</span> a[<span class="Number">2</span>] <span class="Keyword">or</span> <span class="Number">1</span>
<span class="line-numbers"> 319 </span> len<span class="Keyword">:</span> Math.ceil((stop <span class="Keyword">-</span> start) <span class="Keyword">/</span> step)
<span class="line-numbers"> 313 </span> <span class="FunctionArgument"> _.range: start, stop, step </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 314 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 315 </span> <span class="FunctionName">solo</span><span class="Keyword">:</span> a.length <span class="Keyword">&lt;=</span> <span class="Number">1</span>
<span class="line-numbers"> 316 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> <span class="Number">0</span> <span class="Keyword">else</span> a[<span class="Number">0</span>];
<span class="line-numbers"> 317 </span> <span class="FunctionName">stop</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> a[<span class="Number">0</span>] <span class="Keyword">else</span> a[<span class="Number">1</span>];
<span class="line-numbers"> 318 </span> <span class="FunctionName">step</span><span class="Keyword">:</span> a[<span class="Number">2</span>] <span class="Keyword">or</span> <span class="Number">1</span>
<span class="line-numbers"> 319 </span> <span class="FunctionName">len</span><span class="Keyword">:</span> Math.ceil((stop <span class="Keyword">-</span> start) <span class="Keyword">/</span> step)
<span class="line-numbers"> 320 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> len <span class="Keyword">&lt;=</span> <span class="Number">0</span>
<span class="line-numbers"> 321 </span> range<span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(len)
<span class="line-numbers"> 322 </span> idx<span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 321 </span> <span class="FunctionName">range</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(len)
<span class="line-numbers"> 322 </span> <span class="FunctionName">idx</span><span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 323 </span> <span class="Keyword">while</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 324 </span> <span class="Keyword">return</span> range <span class="Keyword">if</span> (<span class="Keyword">if</span> step <span class="Keyword">&gt;</span> <span class="Number">0</span> <span class="Keyword">then</span> i <span class="Keyword">-</span> stop <span class="Keyword">else</span> stop <span class="Keyword">-</span> i) <span class="Keyword">&gt;=</span> <span class="Number">0</span>
<span class="line-numbers"> 325 </span> range[idx]<span class="Keyword">:</span> i
@@ -351,94 +350,94 @@
<span class="line-numbers"> 331 </span>
<span class="line-numbers"> 332 </span> <span class="Comment"><span class="Comment">#</span> Create a function bound to a given object (assigning 'this', and arguments,</span>
<span class="line-numbers"> 333 </span> <span class="Comment"><span class="Comment">#</span> optionally). Binding with arguments is also known as 'curry'.</span>
<span class="line-numbers"> 334 </span> <span class="FunctionName">_.bind</span><span class="Keyword">:</span> <span class="FunctionArgument">func, obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 335 </span> args<span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 334 </span> <span class="FunctionArgument"> _.bind: func, obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 335 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 336 </span> <span class="FunctionArgument"> </span><span class="Storage">=&gt;</span> func.apply(obj <span class="Keyword">or</span> root, args.concat(_.toArray(arguments)))
<span class="line-numbers"> 337 </span>
<span class="line-numbers"> 338 </span>
<span class="line-numbers"> 339 </span> <span class="Comment"><span class="Comment">#</span> Bind all of an object's methods to that object. Useful for ensuring that</span>
<span class="line-numbers"> 340 </span> <span class="Comment"><span class="Comment">#</span> all callbacks defined on an object belong to it.</span>
<span class="line-numbers"> 341 </span> <span class="FunctionName">_.bindAll</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 342 </span> funcs<span class="Keyword">:</span> <span class="Keyword">if</span> arguments.length <span class="Keyword">&gt;</span> <span class="Number">1</span> <span class="Keyword">then</span> _.rest(arguments) <span class="Keyword">else</span> _.functions(obj)
<span class="line-numbers"> 341 </span> <span class="FunctionArgument"> _.bindAll: obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 342 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> <span class="Keyword">if</span> arguments.length <span class="Keyword">&gt;</span> <span class="Number">1</span> <span class="Keyword">then</span> _.rest(arguments) <span class="Keyword">else</span> _.functions(obj)
<span class="line-numbers"> 343 </span> _.each(funcs, (<span class="FunctionArgument">f </span><span class="Storage">=&gt;</span> obj[f]<span class="Keyword">:</span> _.bind(obj[f], obj)))
<span class="line-numbers"> 344 </span> obj
<span class="line-numbers"> 345 </span>
<span class="line-numbers"> 346 </span>
<span class="line-numbers"> 347 </span> <span class="Comment"><span class="Comment">#</span> Delays a function for the given number of milliseconds, and then calls</span>
<span class="line-numbers"> 348 </span> <span class="Comment"><span class="Comment">#</span> it with the arguments supplied.</span>
<span class="line-numbers"> 349 </span> <span class="FunctionName">_.delay</span><span class="Keyword">:</span> <span class="FunctionArgument">func, wait</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 350 </span> args<span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 349 </span> <span class="FunctionArgument"> _.delay: func, wait </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 350 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 351 </span> setTimeout((<span class="Storage">=&gt;</span> func.apply(func, args)), wait)
<span class="line-numbers"> 352 </span>
<span class="line-numbers"> 353 </span>
<span class="line-numbers"> 354 </span> <span class="Comment"><span class="Comment">#</span> Defers a function, scheduling it to run after the current call stack has</span>
<span class="line-numbers"> 355 </span> <span class="Comment"><span class="Comment">#</span> cleared.</span>
<span class="line-numbers"> 356 </span> <span class="FunctionName">_.defer</span><span class="Keyword">:</span> <span class="FunctionArgument">func</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 356 </span> <span class="FunctionArgument"> _.defer: func </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 357 </span> _.delay.apply(_, [func, <span class="Number">1</span>].concat(_.rest(arguments)))
<span class="line-numbers"> 358 </span>
<span class="line-numbers"> 359 </span>
<span class="line-numbers"> 360 </span> <span class="Comment"><span class="Comment">#</span> Returns the first function passed as an argument to the second,</span>
<span class="line-numbers"> 361 </span> <span class="Comment"><span class="Comment">#</span> allowing you to adjust arguments, run code before and after, and</span>
<span class="line-numbers"> 362 </span> <span class="Comment"><span class="Comment">#</span> conditionally execute the original function.</span>
<span class="line-numbers"> 363 </span> <span class="FunctionName">_.wrap</span><span class="Keyword">:</span> <span class="FunctionArgument">func, wrapper</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 363 </span> <span class="FunctionArgument"> _.wrap: func, wrapper </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 364 </span> <span class="FunctionArgument"> </span><span class="Storage">=&gt;</span> wrapper.apply(wrapper, [func].concat(_.toArray(arguments)))
<span class="line-numbers"> 365 </span>
<span class="line-numbers"> 366 </span>
<span class="line-numbers"> 367 </span> <span class="Comment"><span class="Comment">#</span> Returns a function that is the composition of a list of functions, each</span>
<span class="line-numbers"> 368 </span> <span class="Comment"><span class="Comment">#</span> consuming the return value of the function that follows.</span>
<span class="line-numbers"> 369 </span> <span class="FunctionName">_.compose</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 370 </span> funcs<span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 369 </span> <span class="FunctionArgument"> _.compose: </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 370 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 371 </span> <span class="FunctionArgument"> </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 372 </span> args<span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 372 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 373 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [(funcs.length <span class="Keyword">-</span> <span class="Number">1</span>)..<span class="Number">0</span>]
<span class="line-numbers"> 374 </span> args<span class="Keyword">:</span> [funcs[i].apply(<span class="Variable">this</span>, args)]
<span class="line-numbers"> 374 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> [funcs[i].apply(<span class="Variable">this</span>, args)]
<span class="line-numbers"> 375 </span> args[<span class="Number">0</span>]
<span class="line-numbers"> 376 </span>
<span class="line-numbers"> 377 </span>
<span class="line-numbers"> 378 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Object Functions: ----------------------------</span>
<span class="line-numbers"> 379 </span>
<span class="line-numbers"> 380 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the names of an object's properties.</span>
<span class="line-numbers"> 381 </span> <span class="FunctionName">_.keys</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 381 </span> <span class="FunctionArgument"> _.keys: obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 382 </span> <span class="Keyword">return</span> _.range(<span class="Number">0</span>, obj.length) <span class="Keyword">if</span> _.isArray(obj)
<span class="line-numbers"> 383 </span> key <span class="Keyword">for</span> val, key <span class="Keyword">in</span> obj
<span class="line-numbers"> 383 </span> key <span class="Keyword">for</span> key, val <span class="Keyword">ino</span> obj
<span class="line-numbers"> 384 </span>
<span class="line-numbers"> 385 </span>
<span class="line-numbers"> 386 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the values of an object's properties.</span>
<span class="line-numbers"> 387 </span> <span class="FunctionName">_.values</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 387 </span> <span class="FunctionArgument"> _.values: obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 388 </span> _.map(obj, _.identity)
<span class="line-numbers"> 389 </span>
<span class="line-numbers"> 390 </span>
<span class="line-numbers"> 391 </span> <span class="Comment"><span class="Comment">#</span> Return a sorted list of the function names available in Underscore.</span>
<span class="line-numbers"> 392 </span> <span class="FunctionName">_.functions</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 392 </span> <span class="FunctionArgument"> _.functions: obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 393 </span> _.select(_.keys(obj)<span class="FunctionArgument">, key </span><span class="Storage">=&gt;</span> _.isFunction(obj[key])).sort()
<span class="line-numbers"> 394 </span>
<span class="line-numbers"> 395 </span>
<span class="line-numbers"> 396 </span> <span class="Comment"><span class="Comment">#</span> Extend a given object with all of the properties in a source object.</span>
<span class="line-numbers"> 397 </span> <span class="FunctionName">_.extend</span><span class="Keyword">:</span> <span class="FunctionArgument">destination, source</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 398 </span> <span class="Keyword">for</span> val, key <span class="Keyword">in</span> source
<span class="line-numbers"> 397 </span> <span class="FunctionArgument"> _.extend: destination, source </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 398 </span> <span class="Keyword">for</span> key, val <span class="Keyword">ino</span> source
<span class="line-numbers"> 399 </span> destination[key]<span class="Keyword">:</span> val
<span class="line-numbers"> 400 </span> destination
<span class="line-numbers"> 401 </span>
<span class="line-numbers"> 402 </span>
<span class="line-numbers"> 403 </span> <span class="Comment"><span class="Comment">#</span> Create a (shallow-cloned) duplicate of an object.</span>
<span class="line-numbers"> 404 </span> <span class="FunctionName">_.clone</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 404 </span> <span class="FunctionArgument"> _.clone: obj </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 405 </span> <span class="Keyword">return</span> obj.slice(<span class="Number">0</span>) <span class="Keyword">if</span> _.isArray(obj)
<span class="line-numbers"> 406 </span> _.extend({}, obj)
<span class="line-numbers"> 407 </span>
<span class="line-numbers"> 408 </span>
<span class="line-numbers"> 409 </span> <span class="Comment"><span class="Comment">#</span> Invokes interceptor with the obj, and then returns obj.</span>
<span class="line-numbers"> 410 </span> <span class="Comment"><span class="Comment">#</span> The primary purpose of this method is to &quot;tap into&quot; a method chain, in order to perform operations on intermediate results within the chain.</span>
<span class="line-numbers"> 411 </span> <span class="FunctionName">_.tap</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, interceptor</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 411 </span> <span class="FunctionArgument"> _.tap: obj, interceptor </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 412 </span> interceptor(obj)
<span class="line-numbers"> 413 </span> obj
<span class="line-numbers"> 414 </span>
<span class="line-numbers"> 415 </span>
<span class="line-numbers"> 416 </span> <span class="Comment"><span class="Comment">#</span> Perform a deep comparison to check if two objects are equal.</span>
<span class="line-numbers"> 417 </span> <span class="FunctionName">_.isEqual</span><span class="Keyword">:</span> <span class="FunctionArgument">a, b</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 417 </span> <span class="FunctionArgument"> _.isEqual: a, b </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 418 </span> <span class="Comment"><span class="Comment">#</span> Check object identity.</span>
<span class="line-numbers"> 419 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> a <span class="Keyword">is</span> b
<span class="line-numbers"> 420 </span> <span class="Comment"><span class="Comment">#</span> Different types?</span>
<span class="line-numbers"> 421 </span> atype<span class="Keyword">:</span> <span class="Keyword">typeof</span>(a); btype<span class="Keyword">:</span> <span class="Keyword">typeof</span>(b)
<span class="line-numbers"> 421 </span> <span class="FunctionName">atype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(a); <span class="FunctionName">btype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(b)
<span class="line-numbers"> 422 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> btype
<span class="line-numbers"> 423 </span> <span class="Comment"><span class="Comment">#</span> Basic equality test (watch out for coercions).</span>
<span class="line-numbers"> 424 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> <span class="String"><span class="String">`</span>a == b<span class="String">`</span></span>
@@ -461,7 +460,7 @@
<span class="line-numbers"> 441 </span> <span class="Comment"><span class="Comment">#</span> Check for different array lengths before comparing contents.</span>
<span class="line-numbers"> 442 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> a.length <span class="Keyword">and</span> (a.length <span class="Keyword">isnt</span> b.length)
<span class="line-numbers"> 443 </span> <span class="Comment"><span class="Comment">#</span> Nothing else worked, deep compare the contents.</span>
<span class="line-numbers"> 444 </span> aKeys<span class="Keyword">:</span> _.keys(a); bKeys<span class="Keyword">:</span> _.keys(b)
<span class="line-numbers"> 444 </span> <span class="FunctionName">aKeys</span><span class="Keyword">:</span> _.keys(a); <span class="FunctionName">bKeys</span><span class="Keyword">:</span> _.keys(b)
<span class="line-numbers"> 445 </span> <span class="Comment"><span class="Comment">#</span> Different object sizes?</span>
<span class="line-numbers"> 446 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> aKeys.length <span class="Keyword">isnt</span> bKeys.length
<span class="line-numbers"> 447 </span> <span class="Comment"><span class="Comment">#</span> Recursive comparison of contents.</span>
@@ -470,81 +469,81 @@
<span class="line-numbers"> 450 </span>
<span class="line-numbers"> 451 </span>
<span class="line-numbers"> 452 </span> <span class="Comment"><span class="Comment">#</span> Is a given array or object empty?</span>
<span class="line-numbers"> 453 </span> <span class="FunctionName">_.isEmpty</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> _.keys(obj).length <span class="Keyword">is</span> <span class="Number">0</span>
<span class="line-numbers"> 453 </span> <span class="FunctionArgument"> _.isEmpty: obj </span><span class="Storage">=&gt;</span> _.keys(obj).length <span class="Keyword">is</span> <span class="Number">0</span>
<span class="line-numbers"> 454 </span>
<span class="line-numbers"> 455 </span>
<span class="line-numbers"> 456 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a DOM element?</span>
<span class="line-numbers"> 457 </span> <span class="FunctionName">_.isElement</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> obj <span class="Keyword">and</span> obj.nodeType <span class="Keyword">is</span> <span class="Number">1</span>
<span class="line-numbers"> 457 </span> <span class="FunctionArgument"> _.isElement: obj </span><span class="Storage">=&gt;</span> obj <span class="Keyword">and</span> obj.nodeType <span class="Keyword">is</span> <span class="Number">1</span>
<span class="line-numbers"> 458 </span>
<span class="line-numbers"> 459 </span>
<span class="line-numbers"> 460 </span> <span class="Comment"><span class="Comment">#</span> Is a given value an array?</span>
<span class="line-numbers"> 461 </span> <span class="FunctionName">_.isArray</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.concat <span class="Keyword">and</span> obj.unshift)
<span class="line-numbers"> 461 </span> <span class="FunctionArgument"> _.isArray: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.concat <span class="Keyword">and</span> obj.unshift)
<span class="line-numbers"> 462 </span>
<span class="line-numbers"> 463 </span>
<span class="line-numbers"> 464 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable an arguments object?</span>
<span class="line-numbers"> 465 </span> <span class="FunctionName">_.isArguments</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> obj <span class="Keyword">and</span> _.isNumber(obj.length) <span class="Keyword">and</span> <span class="Keyword">!</span>_.isArray(obj) <span class="Keyword">and</span> <span class="Keyword">!</span>propertyIsEnumerable.call(obj, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>)
<span class="line-numbers"> 465 </span> <span class="FunctionArgument"> _.isArguments: obj </span><span class="Storage">=&gt;</span> obj <span class="Keyword">and</span> _.isNumber(obj.length) <span class="Keyword">and</span> <span class="Keyword">!</span>_.isArray(obj) <span class="Keyword">and</span> <span class="Keyword">!</span>propertyIsEnumerable.call(obj, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>)
<span class="line-numbers"> 466 </span>
<span class="line-numbers"> 467 </span>
<span class="line-numbers"> 468 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a function?</span>
<span class="line-numbers"> 469 </span> <span class="FunctionName">_.isFunction</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.constructor <span class="Keyword">and</span> obj.call <span class="Keyword">and</span> obj.apply)
<span class="line-numbers"> 469 </span> <span class="FunctionArgument"> _.isFunction: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.constructor <span class="Keyword">and</span> obj.call <span class="Keyword">and</span> obj.apply)
<span class="line-numbers"> 470 </span>
<span class="line-numbers"> 471 </span>
<span class="line-numbers"> 472 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a string?</span>
<span class="line-numbers"> 473 </span> <span class="FunctionName">_.isString</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span><span class="String">'</span></span> <span class="Keyword">or</span> (obj <span class="Keyword">and</span> obj.charCodeAt <span class="Keyword">and</span> obj.substr))
<span class="line-numbers"> 473 </span> <span class="FunctionArgument"> _.isString: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span><span class="String">'</span></span> <span class="Keyword">or</span> (obj <span class="Keyword">and</span> obj.charCodeAt <span class="Keyword">and</span> obj.substr))
<span class="line-numbers"> 474 </span>
<span class="line-numbers"> 475 </span>
<span class="line-numbers"> 476 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a number?</span>
<span class="line-numbers"> 477 </span> <span class="FunctionName">_.isNumber</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> toString.call(obj) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>[object Number]<span class="String">'</span></span>
<span class="line-numbers"> 477 </span> <span class="FunctionArgument"> _.isNumber: obj </span><span class="Storage">=&gt;</span> toString.call(obj) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>[object Number]<span class="String">'</span></span>
<span class="line-numbers"> 478 </span>
<span class="line-numbers"> 479 </span>
<span class="line-numbers"> 480 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a Date?</span>
<span class="line-numbers"> 481 </span> <span class="FunctionName">_.isDate</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.getTimezoneOffset <span class="Keyword">and</span> obj.setUTCFullYear)
<span class="line-numbers"> 481 </span> <span class="FunctionArgument"> _.isDate: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.getTimezoneOffset <span class="Keyword">and</span> obj.setUTCFullYear)
<span class="line-numbers"> 482 </span>
<span class="line-numbers"> 483 </span>
<span class="line-numbers"> 484 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a regular expression?</span>
<span class="line-numbers"> 485 </span> <span class="FunctionName">_.isRegExp</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.exec <span class="Keyword">and</span> (obj.ignoreCase <span class="Keyword">or</span> obj.ignoreCase <span class="Keyword">is</span> <span class="BuiltInConstant">false</span>))
<span class="line-numbers"> 485 </span> <span class="FunctionArgument"> _.isRegExp: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.exec <span class="Keyword">and</span> (obj.ignoreCase <span class="Keyword">or</span> obj.ignoreCase <span class="Keyword">is</span> <span class="BuiltInConstant">false</span>))
<span class="line-numbers"> 486 </span>
<span class="line-numbers"> 487 </span>
<span class="line-numbers"> 488 </span> <span class="Comment"><span class="Comment">#</span> Is the given value NaN -- this one is interesting. NaN != NaN, and</span>
<span class="line-numbers"> 489 </span> <span class="Comment"><span class="Comment">#</span> isNaN(undefined) == true, so we make sure it's a number first.</span>
<span class="line-numbers"> 490 </span> <span class="FunctionName">_.isNaN</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> _.isNumber(obj) <span class="Keyword">and</span> window.isNaN(obj)
<span class="line-numbers"> 490 </span> <span class="FunctionArgument"> _.isNaN: obj </span><span class="Storage">=&gt;</span> _.isNumber(obj) <span class="Keyword">and</span> window.isNaN(obj)
<span class="line-numbers"> 491 </span>
<span class="line-numbers"> 492 </span>
<span class="line-numbers"> 493 </span> <span class="Comment"><span class="Comment">#</span> Is a given value equal to null?</span>
<span class="line-numbers"> 494 </span> <span class="FunctionName">_.isNull</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">null</span>
<span class="line-numbers"> 494 </span> <span class="FunctionArgument"> _.isNull: obj </span><span class="Storage">=&gt;</span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">null</span>
<span class="line-numbers"> 495 </span>
<span class="line-numbers"> 496 </span>
<span class="line-numbers"> 497 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable undefined?</span>
<span class="line-numbers"> 498 </span> <span class="FunctionName">_.isUndefined</span><span class="Keyword">:</span> <span class="FunctionArgument">obj</span> <span class="Storage">=&gt;</span> <span class="Keyword">typeof</span> obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span>
<span class="line-numbers"> 498 </span> <span class="FunctionArgument"> _.isUndefined: obj </span><span class="Storage">=&gt;</span> <span class="Keyword">typeof</span> obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span>
<span class="line-numbers"> 499 </span>
<span class="line-numbers"> 500 </span>
<span class="line-numbers"> 501 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Utility Functions: --------------------------</span>
<span class="line-numbers"> 502 </span>
<span class="line-numbers"> 503 </span> <span class="Comment"><span class="Comment">#</span> Run Underscore.js in noConflict mode, returning the '_' variable to its</span>
<span class="line-numbers"> 504 </span> <span class="Comment"><span class="Comment">#</span> previous owner. Returns a reference to the Underscore object.</span>
<span class="line-numbers"> 505 </span> <span class="FunctionName">_.noConflict</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 506 </span> root._<span class="Keyword">:</span> previousUnderscore
<span class="line-numbers"> 505 </span> <span class="FunctionArgument"> _.noConflict: </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 506 </span> root.<span class="FunctionName">_</span><span class="Keyword">:</span> previousUnderscore
<span class="line-numbers"> 507 </span> <span class="Variable">this</span>
<span class="line-numbers"> 508 </span>
<span class="line-numbers"> 509 </span>
<span class="line-numbers"> 510 </span> <span class="Comment"><span class="Comment">#</span> Keep the identity function around for default iterators.</span>
<span class="line-numbers"> 511 </span> <span class="FunctionName">_.identity</span><span class="Keyword">:</span> <span class="FunctionArgument">value</span> <span class="Storage">=&gt;</span> value
<span class="line-numbers"> 511 </span> <span class="FunctionArgument"> _.identity: value </span><span class="Storage">=&gt;</span> value
<span class="line-numbers"> 512 </span>
<span class="line-numbers"> 513 </span>
<span class="line-numbers"> 514 </span> <span class="Comment"><span class="Comment">#</span> Break out of the middle of an iteration.</span>
<span class="line-numbers"> 515 </span> <span class="FunctionName">_.breakLoop</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span> <span class="Keyword">throw</span> breaker
<span class="line-numbers"> 515 </span> <span class="FunctionArgument"> _.breakLoop: </span><span class="Storage">=&gt;</span> <span class="Keyword">throw</span> breaker
<span class="line-numbers"> 516 </span>
<span class="line-numbers"> 517 </span>
<span class="line-numbers"> 518 </span> <span class="Comment"><span class="Comment">#</span> Generate a unique integer id (unique within the entire client session).</span>
<span class="line-numbers"> 519 </span> <span class="Comment"><span class="Comment">#</span> Useful for temporary DOM ids.</span>
<span class="line-numbers"> 520 </span> idCounter<span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 521 </span> <span class="FunctionName">_.uniqueId</span><span class="Keyword">:</span> <span class="FunctionArgument">prefix</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 520 </span> <span class="FunctionName">idCounter</span><span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 521 </span> <span class="FunctionArgument"> _.uniqueId: prefix </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 522 </span> (prefix <span class="Keyword">or</span> <span class="String"><span class="String">'</span><span class="String">'</span></span>) <span class="Keyword">+</span> idCounter<span class="Keyword">++</span>
<span class="line-numbers"> 523 </span>
<span class="line-numbers"> 524 </span>
<span class="line-numbers"> 525 </span> <span class="Comment"><span class="Comment">#</span> JavaScript templating a-la ERB, pilfered from John Resig's</span>
<span class="line-numbers"> 526 </span> <span class="Comment"><span class="Comment">#</span> &quot;Secrets of the JavaScript Ninja&quot;, page 83.</span>
<span class="line-numbers"> 527 </span> <span class="FunctionName">_.template</span><span class="Keyword">:</span> <span class="FunctionArgument">str, data</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 527 </span> <span class="FunctionArgument"> _.template: str, data </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 528 </span> <span class="String"><span class="String">`</span>var fn = new Function('obj',</span>
<span class="line-numbers"> 529 </span> <span class="String"> 'var p=[],print=function(){p.push.apply(p,arguments);};' +</span>
<span class="line-numbers"> 530 </span> <span class="String"> 'with(obj){p.push(<span class="UserDefinedConstant">\'</span>' +</span>
@@ -562,55 +561,67 @@
<span class="line-numbers"> 542 </span>
<span class="line-numbers"> 543 </span> <span class="Comment"><span class="Comment">#</span> ------------------------------- Aliases ----------------------------------</span>
<span class="line-numbers"> 544 </span>
<span class="line-numbers"> 545 </span> _.forEach<span class="Keyword">:</span> _.each
<span class="line-numbers"> 546 </span> _.foldl<span class="Keyword">:</span> _.inject<span class="Keyword">:</span> _.reduce
<span class="line-numbers"> 547 </span> _.foldr<span class="Keyword">:</span> _.reduceRight
<span class="line-numbers"> 548 </span> _.filter<span class="Keyword">:</span> _.select
<span class="line-numbers"> 549 </span> _.every<span class="Keyword">:</span> _.all
<span class="line-numbers"> 550 </span> _.some<span class="Keyword">:</span> _.any
<span class="line-numbers"> 551 </span> _.head<span class="Keyword">:</span> _.first
<span class="line-numbers"> 552 </span> _.tail<span class="Keyword">:</span> _.rest
<span class="line-numbers"> 553 </span> _.methods<span class="Keyword">:</span> _.functions
<span class="line-numbers"> 545 </span> _.<span class="FunctionName">forEach</span><span class="Keyword">:</span> _.each
<span class="line-numbers"> 546 </span> _.<span class="FunctionName">foldl</span><span class="Keyword">:</span> _.<span class="FunctionName">inject</span><span class="Keyword">:</span> _.reduce
<span class="line-numbers"> 547 </span> _.<span class="FunctionName">foldr</span><span class="Keyword">:</span> _.reduceRight
<span class="line-numbers"> 548 </span> _.<span class="FunctionName">filter</span><span class="Keyword">:</span> _.select
<span class="line-numbers"> 549 </span> _.<span class="FunctionName">every</span><span class="Keyword">:</span> _.all
<span class="line-numbers"> 550 </span> _.<span class="FunctionName">some</span><span class="Keyword">:</span> _.any
<span class="line-numbers"> 551 </span> _.<span class="FunctionName">head</span><span class="Keyword">:</span> _.first
<span class="line-numbers"> 552 </span> _.<span class="FunctionName">tail</span><span class="Keyword">:</span> _.rest
<span class="line-numbers"> 553 </span> _.<span class="FunctionName">methods</span><span class="Keyword">:</span> _.functions
<span class="line-numbers"> 554 </span>
<span class="line-numbers"> 555 </span>
<span class="line-numbers"> 556 </span> <span class="Comment"><span class="Comment">#</span> /*------------------------ Setup the OOP Wrapper: --------------------------*/</span>
<span class="line-numbers"> 557 </span>
<span class="line-numbers"> 558 </span> <span class="Comment"><span class="Comment">#</span> Helper function to continue chaining intermediate results.</span>
<span class="line-numbers"> 559 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="FunctionArgument">obj, chain</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 559 </span> <span class="FunctionArgument"> result: obj, chain </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 560 </span> <span class="Keyword">if</span> chain <span class="Keyword">then</span> _(obj).chain() <span class="Keyword">else</span> obj
<span class="line-numbers"> 561 </span>
<span class="line-numbers"> 562 </span>
<span class="line-numbers"> 563 </span> <span class="Comment"><span class="Comment">#</span> Add all of the Underscore functions to the wrapper object.</span>
<span class="line-numbers"> 564 </span> _.each(_.functions(_))<span class="FunctionArgument"> name </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 565 </span> method<span class="Keyword">:</span> _[name]
<span class="line-numbers"> 565 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> _[name]
<span class="line-numbers"> 566 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 567 </span> unshift.call(arguments, <span class="Variable">this</span>._wrapped)
<span class="line-numbers"> 568 </span> result(method.apply(_, arguments), <span class="Variable">this</span>._chain)
<span class="line-numbers"> 569 </span>
<span class="line-numbers"> 567 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.toArray(arguments)
<span class="line-numbers"> 568 </span> unshift.call(args, <span class="Variable">this</span>._wrapped)
<span class="line-numbers"> 569 </span> result(method.apply(_, args), <span class="Variable">this</span>._chain)
<span class="line-numbers"> 570 </span>
<span class="line-numbers"> 571 </span> <span class="Comment"><span class="Comment">#</span> Add all mutator Array functions to the wrapper.</span>
<span class="line-numbers"> 572 </span> _.each([<span class="String"><span class="String">'</span>pop<span class="String">'</span></span>, <span class="String"><span class="String">'</span>push<span class="String">'</span></span>, <span class="String"><span class="String">'</span>reverse<span class="String">'</span></span>, <span class="String"><span class="String">'</span>shift<span class="String">'</span></span>, <span class="String"><span class="String">'</span>sort<span class="String">'</span></span>, <span class="String"><span class="String">'</span>splice<span class="String">'</span></span>, <span class="String"><span class="String">'</span>unshift<span class="String">'</span></span>])<span class="FunctionArgument"> name </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 573 </span> method<span class="Keyword">:</span> Array.prototype[name]
<span class="line-numbers"> 574 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 575 </span> method.apply(<span class="Variable">this</span>._wrapped, arguments)
<span class="line-numbers"> 576 </span> result(<span class="Variable">this</span>._wrapped, <span class="Variable">this</span>._chain)
<span class="line-numbers"> 577 </span>
<span class="line-numbers"> 571 </span>
<span class="line-numbers"> 572 </span> <span class="Comment"><span class="Comment">#</span> Add all mutator Array functions to the wrapper.</span>
<span class="line-numbers"> 573 </span> _.each([<span class="String"><span class="String">'</span>pop<span class="String">'</span></span>, <span class="String"><span class="String">'</span>push<span class="String">'</span></span>, <span class="String"><span class="String">'</span>reverse<span class="String">'</span></span>, <span class="String"><span class="String">'</span>shift<span class="String">'</span></span>, <span class="String"><span class="String">'</span>sort<span class="String">'</span></span>, <span class="String"><span class="String">'</span>splice<span class="String">'</span></span>, <span class="String"><span class="String">'</span>unshift<span class="String">'</span></span>])<span class="FunctionArgument"> name </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 574 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
<span class="line-numbers"> 575 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 576 </span> method.apply(<span class="Variable">this</span>._wrapped, arguments)
<span class="line-numbers"> 577 </span> result(<span class="Variable">this</span>._wrapped, <span class="Variable">this</span>._chain)
<span class="line-numbers"> 578 </span>
<span class="line-numbers"> 579 </span> <span class="Comment"><span class="Comment">#</span> Add all accessor Array functions to the wrapper.</span>
<span class="line-numbers"> 580 </span> _.each([<span class="String"><span class="String">'</span>concat<span class="String">'</span></span>, <span class="String"><span class="String">'</span>join<span class="String">'</span></span>, <span class="String"><span class="String">'</span>slice<span class="String">'</span></span>])<span class="FunctionArgument"> name </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 581 </span> method<span class="Keyword">:</span> Array.prototype[name]
<span class="line-numbers"> 582 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 583 </span> result(method.apply(<span class="Variable">this</span>._wrapped, arguments), <span class="Variable">this</span>._chain)
<span class="line-numbers"> 584 </span>
<span class="line-numbers"> 579 </span>
<span class="line-numbers"> 580 </span> <span class="Comment"><span class="Comment">#</span> Add all accessor Array functions to the wrapper.</span>
<span class="line-numbers"> 581 </span> _.each([<span class="String"><span class="String">'</span>concat<span class="String">'</span></span>, <span class="String"><span class="String">'</span>join<span class="String">'</span></span>, <span class="String"><span class="String">'</span>slice<span class="String">'</span></span>])<span class="FunctionArgument"> name </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 582 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
<span class="line-numbers"> 583 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 584 </span> result(method.apply(<span class="Variable">this</span>._wrapped, arguments), <span class="Variable">this</span>._chain)
<span class="line-numbers"> 585 </span>
<span class="line-numbers"> 586 </span> <span class="Comment"><span class="Comment">#</span> Start chaining a wrapped Underscore object.</span>
<span class="line-numbers"> 587 </span> <span class="FunctionName">wrapper.prototype.chain</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="line-numbers"> 588 </span> <span class="Variable">this</span>._chain<span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 589 </span> <span class="Variable">this</span>
<span class="line-numbers"> 590 </span>
<span class="line-numbers"> 586 </span>
<span class="line-numbers"> 587 </span> <span class="Comment"><span class="Comment">#</span> Start chaining a wrapped Underscore object.</span>
<span class="line-numbers"> 588 </span> <span class="FunctionArgument"> wrapper::chain: </span><span class="Storage">=&gt;</span>
<span class="line-numbers"> 589 </span> <span class="Variable">this</span>.<span class="FunctionName">_chain</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 590 </span> <span class="Variable">this</span>
<span class="line-numbers"> 591 </span>
<span class="line-numbers"> 592 </span> <span class="Comment"><span class="Comment">#</span> Extracts the result from a wrapped and chained object.</span>
<span class="line-numbers"> 593 </span> <span class="FunctionName">wrapper.prototype.value</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>._wrapped
</pre>
<span class="line-numbers"> 592 </span>
<span class="line-numbers"> 593 </span> <span class="Comment"><span class="Comment">#</span> Extracts the result from a wrapped and chained object.</span>
<span class="line-numbers"> 594 </span> <span class="FunctionArgument"> wrapper::value: </span><span class="Storage">=&gt;</span> <span class="Variable">this</span>._wrapped
</pre> <p>
<a href="http://validator.w3.org/check?uri=referer">
<img style="border:0"
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" />
</a>
<a href="http://jigsaw.w3.org/css-validator/check?uri=referer">
<img style="border:0;width:88px;height:31px"
src="http://jigsaw.w3.org/css-validator/images/vcss"
alt="Valid CSS!" />
</a>
</p>
</body>
</html>

View File

@@ -141,18 +141,18 @@ aliquam erat volutpat. Ut wisi enim ad."
# Inheritance and calling super.
Animal: =>
Animal.prototype.move: meters =>
Animal::move: meters =>
alert(this.name + " moved " + meters + "m.")
Snake: name => this.name: name
Snake extends Animal
Snake.prototype.move: =>
Snake::move: =>
alert('Slithering...')
super(5)
Horse: name => this.name: name
Horse extends Animal
Horse.prototype.move: =>
Horse::move: =>
alert('Galloping...')
super(45)

View File

@@ -14,9 +14,9 @@
# end
LotteryTicket: {
get_picks: => this.picks
set_picks: nums => this.picks: nums
get_purchase: => this.purchase
get_picks: => this.picks
set_picks: nums => this.picks: nums
get_purchase: => this.purchase
set_purchase: amount => this.purchase: amount
}

View File

@@ -30,7 +30,7 @@
breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
# Create a safe reference to the Underscore object for reference below.
# Create a safe reference to the Underscore object forreference below.
_: root._: obj => new wrapper(obj)
@@ -39,15 +39,15 @@
# Create quick reference variables for speed access to core prototypes.
slice: Array.prototype.slice
unshift: Array.prototype.unshift
toString: Object.prototype.toString
hasOwnProperty: Object.prototype.hasOwnProperty
propertyIsEnumerable: Object.prototype.propertyIsEnumerable
slice: Array::slice
unshift: Array::unshift
toString: Object::toString
hasOwnProperty: Object::hasOwnProperty
propertyIsEnumerable: Object::propertyIsEnumerable
# Current version.
_.VERSION: '0.5.3'
_.VERSION: '0.5.5'
# ------------------------ Collection Functions: ---------------------------
@@ -60,7 +60,7 @@
return obj.forEach(iterator, context) if obj.forEach
if _.isArray(obj) or _.isArguments(obj)
return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
iterator.call(context, val, key, obj) for val, key in obj
iterator.call(context, val, key, obj) for key, val ino obj
catch e
throw e if e isnt breaker
obj
@@ -148,7 +148,7 @@
# based on '==='.
_.include: obj, target =>
return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
for val in obj
for key, val ino obj
return true if val is target
false
@@ -380,7 +380,7 @@
# Retrieve the names of an object's properties.
_.keys: obj =>
return _.range(0, obj.length) if _.isArray(obj)
key for val, key in obj
key for key, val ino obj
# Retrieve the values of an object's properties.
@@ -395,7 +395,7 @@
# Extend a given object with all of the properties in a source object.
_.extend: destination, source =>
for val, key in source
for key, val ino source
destination[key]: val
destination
@@ -564,8 +564,9 @@
_.each(_.functions(_)) name =>
method: _[name]
wrapper.prototype[name]: =>
unshift.call(arguments, this._wrapped)
result(method.apply(_, arguments), this._chain)
args: _.toArray(arguments)
unshift.call(args, this._wrapped)
result(method.apply(_, args), this._chain)
# Add all mutator Array functions to the wrapper.
@@ -584,10 +585,10 @@
# Start chaining a wrapped Underscore object.
wrapper.prototype.chain: =>
wrapper::chain: =>
this._chain: true
this
# Extracts the result from a wrapped and chained object.
wrapper.prototype.value: => this._wrapped
wrapper::value: => this._wrapped

View File

@@ -1,8 +1,6 @@
<!DOCTYPE html>
<html>
<head>
@@ -28,8 +26,8 @@
<p>
<b>Disclaimer:</b>
CoffeeScript is just for fun and seriously alpha. I'm sure that there are still
plenty of holes in the lexer and leaks in the syntax. <i>There is no guarantee,
explicit or implied, of its suitability for any purpose.</i> That said,
plenty of holes in the walls and leaks in the roof. <i>There are no guarantees
that the syntax won't change between versions.</i> That said,
it compiles into clean JavaScript (the good parts) that can use existing
JavaScript libraries seamlessly, and passes through
<a href="http://www.jslint.com/">JSLint</a> without warnings. The compiled
@@ -39,7 +37,7 @@
<p>
<b>Latest Version:</b>
<a href="http://gemcutter.org/gems/coffee-script">0.2.1</a>
<a href="http://gemcutter.org/gems/coffee-script">0.2.2</a>
</p>
<h2>Table of Contents</h2>
@@ -55,7 +53,7 @@
<a href="#conditionals">Conditionals, Ternaries, and Conditional Assignment</a><br />
<a href="#existence">The Existence Operator</a><br />
<a href="#aliases">Aliases</a><br />
<a href="#splats">Splats</a><br />
<a href="#splats">Splats...</a><br />
<a href="#arguments">Arguments are Arrays</a><br />
<a href="#while">While Loops</a><br />
<a href="#comprehensions">Comprehensions (Arrays, Objects, and Ranges)</a><br />
@@ -77,35 +75,35 @@
<p><i>CoffeeScript on the left, compiled JavaScript output on the right.</i></p>
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> Assignment:</span>
number<span class="Keyword">:</span> <span class="Number">42</span>
opposite_day<span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="FunctionName">number</span><span class="Keyword">:</span> <span class="Number">42</span>
<span class="FunctionName">opposite_day</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="Comment"><span class="Comment">#</span> Conditions:</span>
number<span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">42</span> <span class="Keyword">if</span> opposite_day
<span class="FunctionName">number</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">42</span> <span class="Keyword">if</span> opposite_day
<span class="Comment"><span class="Comment">#</span> Functions:</span>
<span class="FunctionName">square</span><span class="Keyword">:</span> <span class="FunctionArgument">x</span> <span class="Storage">=&gt;</span> x <span class="Keyword">*</span> x
<span class="Comment"><span class="Comment">#</span> Arrays:</span>
list<span class="Keyword">:</span> [<span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>]
<span class="FunctionName">list</span><span class="Keyword">:</span> [<span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>]
<span class="Comment"><span class="Comment">#</span> Objects:</span>
math<span class="Keyword">:</span> {
root<span class="Keyword">:</span> Math.sqrt
square<span class="Keyword">:</span> square
<span class="FunctionName">cube</span><span class="Keyword">:</span> <span class="FunctionArgument">x</span> <span class="Storage">=&gt;</span> x <span class="Keyword">*</span> square(x)
<span class="FunctionName">math</span><span class="Keyword">:</span> {
<span class="FunctionName">root</span><span class="Keyword">:</span> Math.sqrt
<span class="FunctionName">square</span><span class="Keyword">:</span> square
<span class="FunctionArgument"> cube: x </span><span class="Storage">=&gt;</span> x <span class="Keyword">*</span> square(x)
}
<span class="Comment"><span class="Comment">#</span> Splats:</span>
race<span class="Keyword">:</span><span class="FunctionArgument"> winner, *runners </span><span class="Storage">=&gt;</span>
<span class="FunctionArgument">race: winner, runners... </span><span class="Storage">=&gt;</span>
print(winner, runners)
<span class="Comment"><span class="Comment">#</span> Existence:</span>
alert(<span class="String"><span class="String">&quot;</span>I knew it!<span class="String">&quot;</span></span>) <span class="Keyword">if</span> elvis<span class="Keyword">?</span>
<span class="Comment"><span class="Comment">#</span> Array comprehensions:</span>
cubed_list<span class="Keyword">:</span> math.cube(num) <span class="Keyword">for</span> num <span class="Keyword">in</span> list
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, race, square;
<span class="FunctionName">cubed_list</span><span class="Keyword">:</span> math.cube(num) <span class="Keyword">for</span> num <span class="Keyword">in</span> list
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
<span class="Comment"><span class="Comment">//</span> Assignment:</span>
number <span class="Keyword">=</span> <span class="Number">42</span>;
opposite_day <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
@@ -139,18 +137,14 @@ race <span class="Keyword">=</span> <span class="Storage">function</span> <span
}
<span class="Comment"><span class="Comment">//</span> Array comprehensions:</span>
cubed_list <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__a <span class="Keyword">=</span> list;
__c <span class="Keyword">=</span> [];
<span class="Keyword">for</span> (__b <span class="Keyword">in</span> __a) {
<span class="Keyword">if</span> (__a.hasOwnProperty(__b)) {
num <span class="Keyword">=</span> __a[__b];
__d <span class="Keyword">=</span> math.cube(num);
__c.<span class="LibraryFunction">push</span>(__d);
}
__c <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> list;
<span class="Keyword">for</span> (__b<span class="Keyword">=</span><span class="Number">0</span>; __b<span class="Keyword">&lt;</span>__a.<span class="LibraryConstant">length</span>; __b<span class="Keyword">++</span>) {
num <span class="Keyword">=</span> __a[__b];
__c.<span class="LibraryFunction">push</span>(math.cube(num));
}
<span class="Keyword">return</span> __c;
})();
</pre><button onclick='javascript: var __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, race, square;
</pre><button onclick='javascript: var __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
// Assignment:
number = 42;
opposite_day = true;
@@ -184,14 +178,10 @@ if ((typeof elvis !== "undefined" && elvis !== null)) {
}
// Array comprehensions:
cubed_list = (function() {
__a = list;
__c = [];
for (__b in __a) {
if (__a.hasOwnProperty(__b)) {
num = __a[__b];
__d = math.cube(num);
__c.push(__d);
}
__c = []; __a = list;
for (__b=0; __b<__a.length; __b++) {
num = __a[__b];
__c.push(math.cube(num));
}
return __c;
})();
@@ -200,9 +190,13 @@ cubed_list = (function() {
<p>
For a longer CoffeeScript example, check out
<a href="documentation/underscore.html">Underscore.coffee</a>, a port
of <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
to CoffeeScript, which, when compiled, can pass the complete Underscore test suite.
Or, clone the source and take a look in the
of the <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
library of helper functions. Underscore.coffee can pass the entire Underscore.js
test suite. The CoffeeScript version is faster than the original for a number
of methods (in general, due to the speed of CoffeeScript's array comprehensions), and
after being minified and gzipped, is only 241 bytes larger than the original
JavaScript version.
Additional examples are included in the source repository, inside the
<a href="http://github.com/jashkenas/coffee-script/tree/master/examples/">examples</a> folder.
</p>
@@ -295,9 +289,15 @@ gem install coffee-script</pre>
<tr>
<td><code>-n, --no-wrap</code></td>
<td>
Compile the JavaScript without the top-level function safety wrapper
or var declarations, for situations where you want to add every
variable to global scope.
Compile the JavaScript without the top-level function safety wrapper.
(Used for CoffeeScript as a Narwhal module.)
</td>
</tr>
<tr>
<td><code>-g, --globals</code></td>
<td>
Suppress all variable declarations at the top-level, effectively adding
those variables to the global scope. (Used by the REPL.)
</td>
</tr>
<tr>
@@ -342,6 +342,13 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
use indentation.
</p>
<p>
You can use newlines to break up your expression into smaller pieces,
as long as CoffeeScript can tell that the line hasn't finished
(similar to how Ruby handles it). For example,
if the line ends in an operator, dot, or keyword.
</p>
<p id="functions">
<b class="header">Functions and Invocation</b>
Functions are defined by a list of parameters, an arrow, and the
@@ -372,8 +379,8 @@ cube = function cube(x) {
<a href="http://json.org">JSON</a>. Equal signs are only needed for
mathy things.
</p>
<div class='code'><pre class="idle">greeting<span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>Hello CoffeeScript<span class="String">&quot;</span></span>
difficulty<span class="Keyword">:</span> <span class="Number">0.5</span>
<div class='code'><pre class="idle"><span class="FunctionName">greeting</span><span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>Hello CoffeeScript<span class="String">&quot;</span></span>
<span class="FunctionName">difficulty</span><span class="Keyword">:</span> <span class="Number">0.5</span>
</pre><pre class="idle"><span class="Storage">var</span> difficulty, greeting;
greeting <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Hello CoffeeScript<span class="String">&quot;</span></span>;
difficulty <span class="Keyword">=</span> <span class="Number">0.5</span>;
@@ -394,15 +401,15 @@ difficulty = 0.5;
assigning local variables, and can be moved around freely. You can mix
and match the two styles.
</p>
<div class='code'><pre class="idle">song<span class="Keyword">:</span> [<span class="String"><span class="String">&quot;</span>do<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>re<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>mi<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>fa<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>so<span class="String">&quot;</span></span>]
<div class='code'><pre class="idle"><span class="FunctionName">song</span><span class="Keyword">:</span> [<span class="String"><span class="String">&quot;</span>do<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>re<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>mi<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>fa<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>so<span class="String">&quot;</span></span>]
ages<span class="Keyword">:</span> {
max<span class="Keyword">:</span> <span class="Number">10</span>
ida<span class="Keyword">:</span> <span class="Number">9</span>
tim<span class="Keyword">:</span> <span class="Number">11</span>
<span class="FunctionName">ages</span><span class="Keyword">:</span> {
<span class="FunctionName">max</span><span class="Keyword">:</span> <span class="Number">10</span>
<span class="FunctionName">ida</span><span class="Keyword">:</span> <span class="Number">9</span>
<span class="FunctionName">tim</span><span class="Keyword">:</span> <span class="Number">11</span>
}
matrix<span class="Keyword">:</span> [
<span class="FunctionName">matrix</span><span class="Keyword">:</span> [
<span class="Number">1</span>, <span class="Number">0</span>, <span class="Number">1</span>
<span class="Number">0</span>, <span class="Number">0</span>, <span class="Number">1</span>
<span class="Number">1</span>, <span class="Number">1</span>, <span class="Number">0</span>
@@ -431,11 +438,11 @@ matrix = [1, 0, 1, 0, 0, 1, 1, 1, 0];
are properly declared within lexical scope &mdash; you never need to write
<tt>var</tt> yourself.
</p>
<div class='code'><pre class="idle">num<span class="Keyword">:</span> <span class="Number">1</span>
<div class='code'><pre class="idle"><span class="FunctionName">num</span><span class="Keyword">:</span> <span class="Number">1</span>
<span class="FunctionName">change_numbers</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
new_num<span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">1</span>
num<span class="Keyword">:</span> <span class="Number">10</span>
new_num<span class="Keyword">:</span> change_numbers()
<span class="FunctionName">new_num</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">1</span>
<span class="FunctionName">num</span><span class="Keyword">:</span> <span class="Number">10</span>
<span class="FunctionName">new_num</span><span class="Keyword">:</span> change_numbers()
</pre><pre class="idle"><span class="Storage">var</span> change_numbers, new_num, num;
num <span class="Keyword">=</span> <span class="Number">1</span>;
change_numbers <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">change_numbers</span>() {
@@ -482,13 +489,13 @@ new_num = change_numbers();
CoffeeScript will compile <b>if</b> statements using the ternary operator
when possible, to make it easier to use the result as an expression.
</p>
<div class='code'><pre class="idle">mood<span class="Keyword">:</span> greatly_improved <span class="Keyword">if</span> singing
<div class='code'><pre class="idle"><span class="FunctionName">mood</span><span class="Keyword">:</span> greatly_improved <span class="Keyword">if</span> singing
<span class="Keyword">if</span> happy <span class="Keyword">and</span> knows_it
claps_hands()
cha_cha_cha()
date<span class="Keyword">:</span> <span class="Keyword">if</span> friday <span class="Keyword">then</span> sue <span class="Keyword">else</span> jill
<span class="FunctionName">date</span><span class="Keyword">:</span> <span class="Keyword">if</span> friday <span class="Keyword">then</span> sue <span class="Keyword">else</span> jill
expensive <span class="Keyword">||</span><span class="Keyword">=</span> do_the_math()
</pre><pre class="idle"><span class="Storage">var</span> date, mood;
@@ -517,7 +524,7 @@ expensive <span class="Keyword">=</span> expensive <span class="Keyword">||</spa
a variable is <b>null</b> or <b>undefined</b>, which makes it analogous
to Ruby's <tt>nil?</tt>
</p>
<div class='code'><pre class="idle">solipsism<span class="Keyword">:</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> mind<span class="Keyword">?</span> <span class="Keyword">and</span> <span class="Keyword">not</span> world<span class="Keyword">?</span>
<div class='code'><pre class="idle"><span class="FunctionName">solipsism</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> mind<span class="Keyword">?</span> <span class="Keyword">and</span> <span class="Keyword">not</span> world<span class="Keyword">?</span>
</pre><pre class="idle"><span class="Storage">var</span> solipsism;
<span class="Keyword">if</span> ((<span class="Keyword">typeof</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> <span class="Keyword">!</span>(<span class="Keyword">typeof</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>)) {
solipsism <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
@@ -554,7 +561,7 @@ expensive <span class="Keyword">=</span> expensive <span class="Keyword">||</spa
</p>
<div class='code'><pre class="idle">launch() <span class="Keyword">if</span> ignition <span class="Keyword">is</span> <span class="BuiltInConstant">on</span>
volume<span class="Keyword">:</span> <span class="Number">10</span> <span class="Keyword">if</span> band <span class="Keyword">isnt</span> spinal_tap
<span class="FunctionName">volume</span><span class="Keyword">:</span> <span class="Number">10</span> <span class="Keyword">if</span> band <span class="Keyword">isnt</span> spinal_tap
let_the_wild_rumpus_begin() <span class="Keyword">unless</span> answer <span class="Keyword">is</span> <span class="BuiltInConstant">no</span>
@@ -573,20 +580,20 @@ car.speed <span class="Keyword">&lt;</span> speed_limit ? accelerate() : <span c
</pre><br class='clear' /></div>
<p id="splats">
<b class="header">Splats</b>
<b class="header">Splats...</b>
The JavaScript <b>arguments object</b> is a useful way to work with
functions that accept variable numbers of arguments. CoffeeScript provides
splats <tt>*</tt>, both for function definition as well as invocation,
splats <tt>...</tt>, both for function definition as well as invocation,
making variable arguments a little bit more palatable.
</p>
<div class='code'><pre class="idle">gold<span class="Keyword">:</span> silver<span class="Keyword">:</span> the_field<span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>unknown<span class="String">&quot;</span></span>
<div class='code'><pre class="idle"><span class="FunctionName">gold</span><span class="Keyword">:</span> <span class="FunctionName">silver</span><span class="Keyword">:</span> <span class="FunctionName">the_field</span><span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>unknown<span class="String">&quot;</span></span>
medalists<span class="Keyword">:</span><span class="FunctionArgument"> first, second, *rest </span><span class="Storage">=&gt;</span>
gold<span class="Keyword">:</span> first
silver<span class="Keyword">:</span> second
the_field<span class="Keyword">:</span> rest
<span class="FunctionArgument">medalists: first, second, rest... </span><span class="Storage">=&gt;</span>
<span class="FunctionName">gold</span><span class="Keyword">:</span> first
<span class="FunctionName">silver</span><span class="Keyword">:</span> second
<span class="FunctionName">the_field</span><span class="Keyword">:</span> rest
contenders<span class="Keyword">:</span> [
<span class="FunctionName">contenders</span><span class="Keyword">:</span> [
<span class="String"><span class="String">&quot;</span>Michael Phelps<span class="String">&quot;</span></span>
<span class="String"><span class="String">&quot;</span>Liu Xiang<span class="String">&quot;</span></span>
<span class="String"><span class="String">&quot;</span>Yao Ming<span class="String">&quot;</span></span>
@@ -599,7 +606,7 @@ contenders<span class="Keyword">:</span> [
<span class="String"><span class="String">&quot;</span>Usain Bolt<span class="String">&quot;</span></span>
]
medalists(<span class="Keyword">*</span>contenders)
medalists(contenders...)
alert(<span class="String"><span class="String">&quot;</span>Gold: <span class="String">&quot;</span></span> <span class="Keyword">+</span> gold)
alert(<span class="String"><span class="String">&quot;</span>Silver: <span class="String">&quot;</span></span> <span class="Keyword">+</span> silver)
@@ -637,8 +644,8 @@ alert("The Field: " + the_field);
<p id="arguments">
<b class="header">Arguments are Arrays</b>
If you reference the <b>arguments object</b> directly, it will be converted
into a real Array, making all of the
<a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array">Array methods</a>
into a real Array, making all of the
<a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array">Array methods</a>
available.
</p>
<div class='code'><pre class="idle"><span class="FunctionName">backwards</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
@@ -691,40 +698,32 @@ backwards("stairway", "to", "heaven");
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>.
</p>
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> Eat lunch.</span>
lunch<span class="Keyword">:</span> eat(food) <span class="Keyword">for</span> food <span class="Keyword">in</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>]
<span class="FunctionName">lunch</span><span class="Keyword">:</span> eat(food) <span class="Keyword">for</span> food <span class="Keyword">in</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>]
<span class="Comment"><span class="Comment">#</span> Naive collision detection.</span>
<span class="Keyword">for</span> roid <span class="Keyword">in</span> asteroids
<span class="Keyword">for</span> roid2 <span class="Keyword">in</span> asteroids <span class="Keyword">when</span> roid <span class="Keyword">isnt</span> roid2
roid.explode() <span class="Keyword">if</span> roid.overlaps(roid2)
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, __f, __g, __h, __i, __j, food, lunch, roid, roid2;
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, __f, __g, food, lunch, roid, roid2;
<span class="Comment"><span class="Comment">//</span> Eat lunch.</span>
lunch <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__a <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>];
__c <span class="Keyword">=</span> [];
<span class="Keyword">for</span> (__b <span class="Keyword">in</span> __a) {
<span class="Keyword">if</span> (__a.hasOwnProperty(__b)) {
food <span class="Keyword">=</span> __a[__b];
__d <span class="Keyword">=</span> eat(food);
__c.<span class="LibraryFunction">push</span>(__d);
}
__c <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>];
<span class="Keyword">for</span> (__b<span class="Keyword">=</span><span class="Number">0</span>; __b<span class="Keyword">&lt;</span>__a.<span class="LibraryConstant">length</span>; __b<span class="Keyword">++</span>) {
food <span class="Keyword">=</span> __a[__b];
__c.<span class="LibraryFunction">push</span>(eat(food));
}
<span class="Keyword">return</span> __c;
})();
<span class="Comment"><span class="Comment">//</span> Naive collision detection.</span>
__e <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (__f <span class="Keyword">in</span> __e) {
<span class="Keyword">if</span> (__e.hasOwnProperty(__f)) {
roid <span class="Keyword">=</span> __e[__f];
__h <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (__i <span class="Keyword">in</span> __h) {
<span class="Keyword">if</span> (__h.hasOwnProperty(__i)) {
roid2 <span class="Keyword">=</span> __h[__i];
<span class="Keyword">if</span> (roid <span class="Keyword">!</span><span class="Keyword">==</span> roid2) {
<span class="Keyword">if</span> (roid.overlaps(roid2)) {
roid.explode();
}
}
__d <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (__e<span class="Keyword">=</span><span class="Number">0</span>; __e<span class="Keyword">&lt;</span>__d.<span class="LibraryConstant">length</span>; __e<span class="Keyword">++</span>) {
roid <span class="Keyword">=</span> __d[__e];
__f <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (__g<span class="Keyword">=</span><span class="Number">0</span>; __g<span class="Keyword">&lt;</span>__f.<span class="LibraryConstant">length</span>; __g<span class="Keyword">++</span>) {
roid2 <span class="Keyword">=</span> __f[__g];
<span class="Keyword">if</span> (roid <span class="Keyword">!</span><span class="Keyword">==</span> roid2) {
<span class="Keyword">if</span> (roid.overlaps(roid2)) {
roid.explode();
}
}
}
@@ -733,58 +732,90 @@ __e <span class="Keyword">=</span> asteroids;
<p>
If you know the start and end of your loop, or would like to step through
in fixed-size increments, you can use a range to specify the start and
end of your comprehension:
end of your comprehension. (The long line-breaking "for" definitions in
the compiled JS below allow ranges to count downwards, as well as upwards).
</p>
<div class='code'><pre class="idle"><span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...eggs.length] <span class="Keyword">by</span> <span class="Number">12</span>
dozen_eggs<span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen))
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, dozen_eggs, i;
__d <span class="Keyword">=</span> <span class="Number">0</span>;
__e <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
<span class="Keyword">for</span> (__c<span class="Keyword">=</span><span class="Number">0</span>, i<span class="Keyword">=</span>__d; (__d <span class="Keyword">&lt;=</span> __e ? i <span class="Keyword">&lt;</span> __e : i <span class="Keyword">&gt;</span> __e); (__d <span class="Keyword">&lt;=</span> __e ? i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span> : i <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">12</span>), __c<span class="Keyword">++</span>) {
dozen_eggs <span class="Keyword">=</span> eggs.<span class="LibraryFunction">slice</span>(i, i <span class="Keyword">+</span> <span class="Number">12</span>);
deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen));
}
</pre><br class='clear' /></div>
<p>
Comprehensions can also be used to iterate over the values and keys in
an object:
</p>
<div class='code'><pre class="idle">years_old<span class="Keyword">:</span> {max<span class="Keyword">:</span> <span class="Number">10</span>, ida<span class="Keyword">:</span> <span class="Number">9</span>, tim<span class="Keyword">:</span> <span class="Number">11</span>}
<div class='code'><pre class="idle"><span class="FunctionName">countdown</span><span class="Keyword">:</span> num <span class="Keyword">for</span> num <span class="Keyword">in</span> [<span class="Number">10</span>..<span class="Number">1</span>]
ages<span class="Keyword">:</span> child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age <span class="Keyword">for</span> age, child <span class="Keyword">in</span> years_old
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, age, ages, child, years_old;
<span class="FunctionName">egg_delivery</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...eggs.length] <span class="Keyword">by</span> <span class="Number">12</span>
<span class="FunctionName">dozen_eggs</span><span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen))
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, countdown, egg_delivery, num;
countdown <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__b <span class="Keyword">=</span> []; __d <span class="Keyword">=</span> <span class="Number">10</span>; __e <span class="Keyword">=</span> <span class="Number">1</span>;
<span class="Keyword">for</span> (__c<span class="Keyword">=</span><span class="Number">0</span>, num<span class="Keyword">=</span>__d; (__d <span class="Keyword">&lt;=</span> __e ? num <span class="Keyword">&lt;=</span> __e : num <span class="Keyword">&gt;=</span> __e); (__d <span class="Keyword">&lt;=</span> __e ? num <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">1</span> : num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>), __c<span class="Keyword">++</span>) {
__b.<span class="LibraryFunction">push</span>(num);
}
<span class="Keyword">return</span> __b;
})();
egg_delivery <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">egg_delivery</span>() {
<span class="Storage">var</span> __f, __g, __h, __i, __j, dozen_eggs, i;
__g <span class="Keyword">=</span> []; __i <span class="Keyword">=</span> <span class="Number">0</span>; __j <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
<span class="Keyword">for</span> (__h<span class="Keyword">=</span><span class="Number">0</span>, i<span class="Keyword">=</span>__i; (__i <span class="Keyword">&lt;=</span> __j ? i <span class="Keyword">&lt;</span> __j : i <span class="Keyword">&gt;</span> __j); (__i <span class="Keyword">&lt;=</span> __j ? i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span> : i <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">12</span>), __h<span class="Keyword">++</span>) {
__g.<span class="LibraryFunction">push</span>((<span class="Storage">function</span>() {
dozen_eggs <span class="Keyword">=</span> eggs.<span class="LibraryFunction">slice</span>(i, i <span class="Keyword">+</span> <span class="Number">12</span>);
<span class="Keyword">return</span> deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen));
})());
}
<span class="Keyword">return</span> __g;
};
</pre><button onclick='javascript: var __a, __b, __c, __d, __e, countdown, egg_delivery, num;
countdown = (function() {
__b = []; __d = 10; __e = 1;
for (__c=0, num=__d; (__d <= __e ? num <= __e : num >= __e); (__d <= __e ? num += 1 : num -= 1), __c++) {
__b.push(num);
}
return __b;
})();
egg_delivery = function egg_delivery() {
var __f, __g, __h, __i, __j, dozen_eggs, i;
__g = []; __i = 0; __j = eggs.length;
for (__h=0, i=__i; (__i <= __j ? i < __j : i > __j); (__i <= __j ? i += 12 : i -= 12), __h++) {
__g.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
})());
}
return __g;
};
;alert(countdown);'>run: countdown</button><br class='clear' /></div>
<p>
Comprehensions can also be used to iterate over the keys and values in
an object. Use <tt>ino</tt> to signal comprehension over an object instead
of an array.
</p>
<div class='code'><pre class="idle"><span class="FunctionName">years_old</span><span class="Keyword">:</span> {<span class="FunctionName">max</span><span class="Keyword">:</span> <span class="Number">10</span>, <span class="FunctionName">ida</span><span class="Keyword">:</span> <span class="Number">9</span>, <span class="FunctionName">tim</span><span class="Keyword">:</span> <span class="Number">11</span>}
<span class="FunctionName">ages</span><span class="Keyword">:</span> child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age <span class="Keyword">for</span> child, age <span class="Keyword">ino</span> years_old
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, age, ages, child, years_old;
years_old <span class="Keyword">=</span> {
max: <span class="Number">10</span>,
ida: <span class="Number">9</span>,
tim: <span class="Number">11</span>
};
ages <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__a <span class="Keyword">=</span> years_old;
__b <span class="Keyword">=</span> [];
__b <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> years_old;
<span class="Keyword">for</span> (child <span class="Keyword">in</span> __a) {
age <span class="Keyword">=</span> __a[child];
<span class="Keyword">if</span> (__a.hasOwnProperty(child)) {
age <span class="Keyword">=</span> __a[child];
__c <span class="Keyword">=</span> child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age;
__b.<span class="LibraryFunction">push</span>(__c);
__b.<span class="LibraryFunction">push</span>(child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age);
}
}
<span class="Keyword">return</span> __b;
})();
</pre><button onclick='javascript: var __a, __b, __c, age, ages, child, years_old;
</pre><button onclick='javascript: var __a, __b, age, ages, child, years_old;
years_old = {
max: 10,
ida: 9,
tim: 11
};
ages = (function() {
__a = years_old;
__b = [];
__b = []; __a = years_old;
for (child in __a) {
age = __a[child];
if (__a.hasOwnProperty(child)) {
age = __a[child];
__c = child + " is " + age;
__b.push(__c);
__b.push(child + " is " + age);
}
}
return __b;
@@ -800,11 +831,11 @@ ages = (function() {
the slice, and the second is the index of the last one. Three dots signify
a range that excludes the end.
</p>
<div class='code'><pre class="idle">numbers<span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
<div class='code'><pre class="idle"><span class="FunctionName">numbers</span><span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
three_to_six<span class="Keyword">:</span> numbers[<span class="Number">3</span>..<span class="Number">6</span>]
<span class="FunctionName">three_to_six</span><span class="Keyword">:</span> numbers[<span class="Number">3</span>..<span class="Number">6</span>]
numbers_copy<span class="Keyword">:</span> numbers[<span class="Number">0</span>...numbers.length]
<span class="FunctionName">numbers_copy</span><span class="Keyword">:</span> numbers[<span class="Number">0</span>...numbers.length]
</pre><pre class="idle"><span class="Storage">var</span> numbers, numbers_copy, three_to_six;
numbers <span class="Keyword">=</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>];
@@ -819,7 +850,7 @@ numbers_copy = numbers.slice(0, numbers.length);
The same syntax can be used with assignment to replace a segment of an
array with new values (to splice it).
</p>
<div class='code'><pre class="idle">numbers<span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
<div class='code'><pre class="idle"><span class="FunctionName">numbers</span><span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
numbers[<span class="Number">3</span>..<span class="Number">6</span>]<span class="Keyword">:</span> [<span class="Keyword">-</span><span class="Number">3</span>, <span class="Keyword">-</span><span class="Number">4</span>, <span class="Keyword">-</span><span class="Number">5</span>, <span class="Keyword">-</span><span class="Number">6</span>]
@@ -849,7 +880,7 @@ numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6]));
<span class="Keyword">else</span>
<span class="String"><span class="String">&quot;</span>C<span class="String">&quot;</span></span>
eldest<span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Number">24</span> <span class="Keyword">&gt;</span> <span class="Number">21</span> <span class="Keyword">then</span> <span class="String"><span class="String">&quot;</span>Liz<span class="String">&quot;</span></span> <span class="Keyword">else</span> <span class="String"><span class="String">&quot;</span>Ike<span class="String">&quot;</span></span>
<span class="FunctionName">eldest</span><span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Number">24</span> <span class="Keyword">&gt;</span> <span class="Number">21</span> <span class="Keyword">then</span> <span class="String"><span class="String">&quot;</span>Liz<span class="String">&quot;</span></span> <span class="Keyword">else</span> <span class="String"><span class="String">&quot;</span>Ike<span class="String">&quot;</span></span>
</pre><pre class="idle"><span class="Storage">var</span> eldest, grade;
grade <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">grade</span>(<span class="FunctionArgument">student</span>) {
<span class="Keyword">if</span> (student.excellent_work) {
@@ -873,11 +904,16 @@ grade = function grade(student) {
};
eldest = 24 > 21 ? "Liz" : "Ike";
;alert(eldest);'>run: eldest</button><br class='clear' /></div>
<p>
Even though functions will always return their final value, it's both possible
and encouraged to return early from a function body writing out the explicit
return (<tt>return value</tt>), when you know that you're done.
</p>
<p>
Because variable declarations occur at the top of scope, assignment can
be used within expressions, even for variables that haven't been seen before:
</p>
<div class='code'><pre class="idle">six<span class="Keyword">:</span> (one<span class="Keyword">:</span> <span class="Number">1</span>) <span class="Keyword">+</span> (two<span class="Keyword">:</span> <span class="Number">2</span>) <span class="Keyword">+</span> (three<span class="Keyword">:</span> <span class="Number">3</span>)
<div class='code'><pre class="idle"><span class="FunctionName">six</span><span class="Keyword">:</span> (<span class="FunctionName">one</span><span class="Keyword">:</span> <span class="Number">1</span>) <span class="Keyword">+</span> (<span class="FunctionName">two</span><span class="Keyword">:</span> <span class="Number">2</span>) <span class="Keyword">+</span> (<span class="FunctionName">three</span><span class="Keyword">:</span> <span class="Number">3</span>)
</pre><pre class="idle"><span class="Storage">var</span> one, six, three, two;
six <span class="Keyword">=</span> (one <span class="Keyword">=</span> <span class="Number">1</span>) <span class="Keyword">+</span> (two <span class="Keyword">=</span> <span class="Number">2</span>) <span class="Keyword">+</span> (three <span class="Keyword">=</span> <span class="Number">3</span>);
</pre><button onclick='javascript: var one, six, three, two;
@@ -891,31 +927,25 @@ six = (one = 1) + (two = 2) + (three = 3);
</p>
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> The first ten global properties.</span>
globals<span class="Keyword">:</span> (name <span class="Keyword">for</span> property, name <span class="Keyword">in</span> window)[<span class="Number">0</span>...<span class="Number">10</span>]
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, globals, name, property;
<span class="FunctionName">globals</span><span class="Keyword">:</span> (name <span class="Keyword">for</span> name <span class="Keyword">ino</span> window)[<span class="Number">0</span>...<span class="Number">10</span>]
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, globals, name;
<span class="Comment"><span class="Comment">//</span> The first ten global properties.</span>
globals <span class="Keyword">=</span> ((<span class="Storage">function</span>() {
__a <span class="Keyword">=</span> <span class="LibraryClassType">window</span>;
__b <span class="Keyword">=</span> [];
__b <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> <span class="LibraryClassType">window</span>;
<span class="Keyword">for</span> (name <span class="Keyword">in</span> __a) {
<span class="Keyword">if</span> (__a.hasOwnProperty(name)) {
property <span class="Keyword">=</span> __a[name];
__c <span class="Keyword">=</span> name;
__b.<span class="LibraryFunction">push</span>(__c);
__b.<span class="LibraryFunction">push</span>(name);
}
}
<span class="Keyword">return</span> __b;
})()).<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>);
</pre><button onclick='javascript: var __a, __b, __c, globals, name, property;
</pre><button onclick='javascript: var __a, __b, globals, name;
// The first ten global properties.
globals = ((function() {
__a = window;
__b = [];
__b = []; __a = window;
for (name in __a) {
if (__a.hasOwnProperty(name)) {
property = __a[name];
__c = name;
__b.push(__c);
__b.push(name);
}
}
return __b;
@@ -929,20 +959,20 @@ globals = ((function() {
<span class="Keyword">try</span>
nonexistent <span class="Keyword">/</span> <span class="BuiltInConstant">undefined</span>
<span class="Keyword">catch</span> error
<span class="String"><span class="String">&quot;</span>The error is: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error
<span class="String"><span class="String">&quot;</span>Caught an error: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error
)
</pre><pre class="idle"><span class="LibraryFunction">alert</span>((<span class="Storage">function</span>() {
<span class="Keyword">try</span> {
<span class="Keyword">return</span> nonexistent / undefined;
} <span class="Keyword">catch</span> (error) {
<span class="Keyword">return</span> <span class="String"><span class="String">&quot;</span>The error is: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error;
<span class="Keyword">return</span> <span class="String"><span class="String">&quot;</span>Caught an error: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error;
}
})());
</pre><button onclick='javascript: alert((function() {
try {
return nonexistent / undefined;
} catch (error) {
return "The error is: " + error;
return "Caught an error: " + error;
}
})());
;'>run</button><br class='clear' /></div>
@@ -959,29 +989,32 @@ globals = ((function() {
be completely usable if it weren't for a couple of small exceptions:
it's awkward to call <b>super</b> (the prototype object's
implementation of the current function), and it's awkward to correctly
set the prototype chain. CoffeeScript provides <tt>extends</tt>
to help with prototype setup, and converts
<tt>super()</tt> calls into calls against the immediate ancestor's
method of the same name.
set the prototype chain.
</p>
<p>
CoffeeScript provides <tt>extends</tt>
to help with prototype setup, <tt>::</tt> for quick access to an
object's prototype, and converts <tt>super()</tt> into a call against
the immediate ancestor's method of the same name.
</p>
<div class='code'><pre class="idle"><span class="FunctionName">Animal</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="FunctionName">Animal.prototype.move</span><span class="Keyword">:</span> <span class="FunctionArgument">meters</span> <span class="Storage">=&gt;</span>
<span class="FunctionName">Animal::move</span><span class="Keyword">:</span> <span class="FunctionArgument">meters</span> <span class="Storage">=&gt;</span>
alert(<span class="Variable">this</span>.name <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> moved <span class="String">&quot;</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>m.<span class="String">&quot;</span></span>)
<span class="FunctionName">Snake</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.name<span class="Keyword">:</span> name
<span class="FunctionName">Snake</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.<span class="FunctionName">name</span><span class="Keyword">:</span> name
Snake <span class="Variable">extends</span> Animal
<span class="FunctionName">Snake.prototype.move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="FunctionName">Snake::move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
alert(<span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>)
<span class="Variable">super</span>(<span class="Number">5</span>)
<span class="FunctionName">Horse</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.name<span class="Keyword">:</span> name
<span class="FunctionName">Horse</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.<span class="FunctionName">name</span><span class="Keyword">:</span> name
Horse <span class="Variable">extends</span> Animal
<span class="FunctionName">Horse.prototype.move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="FunctionName">Horse::move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
alert(<span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>)
<span class="Variable">super</span>(<span class="Number">45</span>)
sam<span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span>(<span class="String"><span class="String">&quot;</span>Sammy the Python<span class="String">&quot;</span></span>)
tom<span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span>(<span class="String"><span class="String">&quot;</span>Tommy the Palomino<span class="String">&quot;</span></span>)
<span class="FunctionName">sam</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span>(<span class="String"><span class="String">&quot;</span>Sammy the Python<span class="String">&quot;</span></span>)
<span class="FunctionName">tom</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span>(<span class="String"><span class="String">&quot;</span>Tommy the Palomino<span class="String">&quot;</span></span>)
sam.move()
tom.move()
@@ -989,27 +1022,35 @@ tom.move()
</pre><pre class="idle"><span class="Storage">var</span> Animal, Horse, Snake, sam, tom;
</pre><pre class="idle"><span class="Storage">var</span> Animal, Horse, Snake, __a, __b, sam, tom;
Animal <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">Animal</span>() {
};
<span class="LibraryClassType">Animal</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span> <span class="FunctionName">move</span>(<span class="FunctionArgument">meters</span>) {
<span class="Keyword">return</span> <span class="LibraryFunction">alert</span>(<span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> moved <span class="String">&quot;</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>m.<span class="String">&quot;</span></span>);
};
Snake <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">Snake</span>(<span class="FunctionArgument">name</span>) {
<span class="Keyword">return</span> <span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> name;
<span class="Storage">var</span> __a;
__a <span class="Keyword">=</span> <span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> name;
<span class="Keyword">return</span> Snake <span class="Keyword">===</span> <span class="Variable">this</span>.<span class="LibraryConstant">constructor</span> ? <span class="Variable">this</span> : __a;
};
<span class="FunctionName">__a</span> = <span class="Storage">function</span>(){};
<span class="LibraryClassType">__a</span>.<span class="LibraryConstant">prototype</span> = Animal.<span class="LibraryConstant">prototype</span>;
Snake.__superClass__ <span class="Keyword">=</span> Animal.<span class="LibraryConstant">prototype</span>;
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">Animal</span>();
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">__a</span>();
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">constructor</span> = Snake;
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span> <span class="FunctionName">move</span>() {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>);
<span class="Keyword">return</span> Snake.__superClass__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">5</span>);
};
Horse <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">Horse</span>(<span class="FunctionArgument">name</span>) {
<span class="Keyword">return</span> <span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> name;
<span class="Storage">var</span> __b;
__b <span class="Keyword">=</span> <span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> name;
<span class="Keyword">return</span> Horse <span class="Keyword">===</span> <span class="Variable">this</span>.<span class="LibraryConstant">constructor</span> ? <span class="Variable">this</span> : __b;
};
<span class="FunctionName">__b</span> = <span class="Storage">function</span>(){};
<span class="LibraryClassType">__b</span>.<span class="LibraryConstant">prototype</span> = Animal.<span class="LibraryConstant">prototype</span>;
Horse.__superClass__ <span class="Keyword">=</span> Animal.<span class="LibraryConstant">prototype</span>;
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">Animal</span>();
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">__b</span>();
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">constructor</span> = Horse;
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span> <span class="FunctionName">move</span>() {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>);
@@ -1019,27 +1060,35 @@ sam <span class="Keyword">=</span> <span class="Keyword">new</span> <span class=
tom <span class="Keyword">=</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span>(<span class="String"><span class="String">&quot;</span>Tommy the Palomino<span class="String">&quot;</span></span>);
sam.move();
tom.move();
</pre><button onclick='javascript: var Animal, Horse, Snake, sam, tom;
</pre><button onclick='javascript: var Animal, Horse, Snake, __a, __b, sam, tom;
Animal = function Animal() {
};
Animal.prototype.move = function move(meters) {
return alert(this.name + " moved " + meters + "m.");
};
Snake = function Snake(name) {
return this.name = name;
var __a;
__a = this.name = name;
return Snake === this.constructor ? this : __a;
};
__a = function(){};
__a.prototype = Animal.prototype;
Snake.__superClass__ = Animal.prototype;
Snake.prototype = new Animal();
Snake.prototype = new __a();
Snake.prototype.constructor = Snake;
Snake.prototype.move = function move() {
alert("Slithering...");
return Snake.__superClass__.move.call(this, 5);
};
Horse = function Horse(name) {
return this.name = name;
var __b;
__b = this.name = name;
return Horse === this.constructor ? this : __b;
};
__b = function(){};
__b.prototype = Animal.prototype;
Horse.__superClass__ = Animal.prototype;
Horse.prototype = new Animal();
Horse.prototype = new __b();
Horse.prototype.constructor = Horse;
Horse.prototype.move = function move() {
alert("Galloping...");
@@ -1058,8 +1107,8 @@ tom.move();
final functions easier to pass, CoffeeScript includes block syntax,
so you don't have to close the parentheses on the other side.
</p>
<div class='code'><pre class="idle"><span class="Keyword">$</span>(<span class="String"><span class="String">'</span>table.list<span class="String">'</span></span>).each()<span class="FunctionArgument"> table </span><span class="Storage">=&gt;</span>
<span class="Keyword">$</span>(<span class="String"><span class="String">'</span>tr.account<span class="String">'</span></span>, table).each()<span class="FunctionArgument"> row </span><span class="Storage">=&gt;</span>
<div class='code'><pre class="idle">$(<span class="String"><span class="String">'</span>table.list<span class="String">'</span></span>).each()<span class="FunctionArgument"> table </span><span class="Storage">=&gt;</span>
$(<span class="String"><span class="String">'</span>tr.account<span class="String">'</span></span>, table).each()<span class="FunctionArgument"> row </span><span class="Storage">=&gt;</span>
row.show()
row.highlight()
</pre><pre class="idle"><span class="Keyword">$</span>(<span class="String"><span class="String">'</span>table.list<span class="String">'</span></span>).each(<span class="Storage">function</span>(table) {
@@ -1075,7 +1124,7 @@ tom.move();
If you ever need to interpolate literal JavaScript snippets, you can
use backticks to pass JavaScript straight through.
</p>
<div class='code'><pre class="idle">hi<span class="Keyword">:</span> <span class="String"><span class="String">`</span>function() {</span>
<div class='code'><pre class="idle"><span class="FunctionName">hi</span><span class="Keyword">:</span> <span class="String"><span class="String">`</span>function() {</span>
<span class="String"> return [document.title, &quot;Hello JavaScript&quot;].join(&quot;: &quot;);</span>
<span class="String">}<span class="String">`</span></span>
@@ -1151,7 +1200,7 @@ return [document.title, "Hello JavaScript"].join(": ");
<b class="header">Multiline Strings</b>
Multiline strings are allowed in CoffeeScript.
</p>
<div class='code'><pre class="idle">moby_dick<span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>Call me Ishmael. Some years ago --</span>
<div class='code'><pre class="idle"><span class="FunctionName">moby_dick</span><span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>Call me Ishmael. Some years ago --</span>
<span class="String">never mind how long precisely -- having little</span>
<span class="String">or no money in my purse, and nothing particular</span>
<span class="String">to interest me on shore, I thought I would sail</span>
@@ -1180,12 +1229,15 @@ world...";
<ul>
<li>
<a href="http://github.com/jashkenas/coffee-script/">Source Code</a><br />
Use <tt>bin/coffee</tt> to test your changes, or <tt>rake gem:install</tt> to
create and install a custom version of the gem. If you're hacking on the
parser, use <tt>rake build:parser</tt> to rebuild it.
After checking out the source, make sure to run <tt>rake build:parser</tt>
to generate an up-to-date version of the Racc parser.
Use <tt>bin/coffee</tt> to test your changes,
<tt>rake test</tt> to run the test suite,
and <tt>rake gem:install</tt> to
create and install a custom version of the gem.
</li>
<li>
<a href="http://github.com/jashkenas/coffee-script/issues">Bugs and Feature Requests</a>
<a href="http://github.com/jashkenas/coffee-script/issues">Bugs, Feature Requests, and General Discussion</a>
</li>
<li>
<a href="http://github.com/jnicklas/bistro_car">BistroCar</a><br />
@@ -1199,19 +1251,14 @@ world...";
<h2 id="contributing">Contributing</h2>
<p>
Here's a wish list of things that would be wonderful to have in
CoffeeScript:
Here's a wish list of things that would be wonderful to have contributed:
</p>
<ul>
<li>
A clean, safe syntax for manipulating the prototype chain, and performing
inheritance. <a href="#inheritance"><b>extends</b> and <b>super</b></a> are the start of this, but
aren't a complete answer.
</li>
<li>
A CoffeeScript version of the compiler, perhaps using Alessandro Warth's
<a href="http://tinlizzie.org/ometa/">OMeta</a>.
<a href="http://github.com/jashkenas/coffee-script/issues#issue/8">
A CoffeeScript version of the compiler.
</a>
</li>
<li>
Test cases for any syntax errors you encounter that you think CoffeeScript
@@ -1234,6 +1281,27 @@ world...";
<h2 id="change_log">Change Log</h2>
<p>
<b class="header" style="margin-top: 20px;">0.2.2</b>
When performing a comprehension over an object, use <tt>ino</tt>, instead
of <tt>in</tt>, which helps us generate smaller, more efficient code at
compile time.
<br />
Added <tt>::</tt> as a shorthand for saying <tt>.prototype.</tt>
<br />
The "splat" symbol has been changed from a prefix asterisk <tt>*</tt>, to
a postfix ellipsis <tt>...</tt>
<br />
Added JavaScript's <tt>in</tt> operator,
empty <tt>return</tt> statements, and empty <tt>while</tt> loops.
<br />
Constructor functions that start with capital letters now include a
safety check to make sure that the new instance of the object is returned.
<br />
The <tt>extends</tt> keyword now functions identically to <tt>goog.inherits</tt>
in Google's Closure Library.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.2.1</b>
Arguments objects are now converted into real arrays when referenced.

View File

@@ -10,7 +10,7 @@ require "coffee_script/parse_error"
# Namespace for all CoffeeScript internal classes.
module CoffeeScript
VERSION = '0.2.1' # Keep in sync with the gemspec.
VERSION = '0.2.2' # Keep in sync with the gemspec.
# Compile a script (String or IO) to JavaScript.
def self.compile(script, options={})

View File

@@ -10,6 +10,10 @@
</array>
<key>name</key>
<string>CoffeeScript</string>
<key>foldingStartMarker</key>
<string>^.*[:=] \{[^\}]*$</string>
<key>foldingStopMarker</key>
<string>\s*\}</string>
<key>patterns</key>
<array>
<dict>
@@ -39,7 +43,7 @@
<key>comment</key>
<string>match stuff like: funcName: =&gt; … </string>
<key>match</key>
<string>([a-zA-Z0-9_?.$*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=&gt;)</string>
<string>([a-zA-Z0-9_?.$:*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=&gt;)</string>
<key>name</key>
<string>meta.function.coffee</string>
</dict>
@@ -60,7 +64,7 @@
<key>comment</key>
<string>match stuff like: a =&gt; … </string>
<key>match</key>
<string>([a-zA-Z0-9_?., $*]*)\s*(=&gt;)</string>
<string>([a-zA-Z0-9_?., $:*]*)\s*(=&gt;)</string>
<key>name</key>
<string>meta.inline.function.coffee</string>
</dict>
@@ -210,7 +214,7 @@
</dict>
<dict>
<key>match</key>
<string>\b([a-zA-Z$_]\w*)(\:)\s</string>
<string>\b([a-zA-Z$_](\w|\$|:)*)(\:)\s</string>
<key>name</key>
<string>variable.assignment.coffee</string>
<key>captures</key>
@@ -220,7 +224,7 @@
<key>name</key>
<string>entity.name.function.coffee</string>
</dict>
<key>2</key>
<key>3</key>
<dict>
<key>name</key>
<string>keyword.operator.coffee</string>
@@ -259,7 +263,7 @@
</dict>
<dict>
<key>match</key>
<string>!|\$|%|&amp;|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\?|\|\||\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(in|instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
<string>!|%|&amp;|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\?|\|\||\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(in|ino|instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
<key>name</key>
<string>keyword.operator.coffee</string>
</dict>

View File

@@ -1,7 +1,13 @@
require 'optparse'
require 'fileutils'
require 'open3'
require File.expand_path(File.dirname(__FILE__) + '/../coffee-script')
begin
require File.expand_path(File.dirname(__FILE__) + '/../coffee-script')
rescue LoadError => e
puts(e.message)
puts("use \"rake build:parser\" to regenerate parser.rb")
exit(1)
end
module CoffeeScript
@@ -133,6 +139,7 @@ Usage:
begin
options = {}
options[:no_wrap] = true if @options[:no_wrap]
options[:globals] = true if @options[:globals]
CoffeeScript.compile(script, options)
rescue CoffeeScript::ParseError, SyntaxError => e
STDERR.puts "#{source}: #{e.message}"
@@ -187,9 +194,12 @@ Usage:
opts.on('-v', '--verbose', 'print at every step of code generation') do |v|
ENV['VERBOSE'] = 'true'
end
opts.on('-n', '--no-wrap', 'raw output, no safety wrapper or vars') do |n|
opts.on('-n', '--no-wrap', 'raw output, no function safety wrapper') do |n|
@options[:no_wrap] = true
end
opts.on('-g', '--globals', 'attach all top-level variable as globals') do |n|
@options[:globals] = true
end
opts.on_tail('--install-bundle', 'install the CoffeeScript TextMate bundle') do |i|
install_bundle
exit

View File

@@ -1,14 +1,14 @@
class Parser
# Declare tokens produced by the lexer
# Declare terminal tokens produced by the lexer.
token IF ELSE UNLESS
token NUMBER STRING REGEX
token TRUE FALSE YES NO ON OFF
token IDENTIFIER PROPERTY_ACCESS
token CODE PARAM PARAM_SPLAT NEW RETURN
token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS
token CODE PARAM NEW RETURN
token TRY CATCH FINALLY THROW
token BREAK CONTINUE
token FOR IN BY WHEN WHILE
token FOR IN INO BY WHEN WHILE
token SWITCH LEADING_WHEN
token DELETE INSTANCEOF TYPEOF
token SUPER EXTENDS
@@ -21,7 +21,7 @@ token INDENT OUTDENT
# Declare order of operations.
prechigh
left '?'
nonassoc UMINUS PARAM_SPLAT SPLAT NOT '!' '!!' '~' '++' '--'
nonassoc UMINUS NOT '!' '!!' '~' '++' '--'
left '*' '/' '%'
left '+' '-'
left '<<' '>>' '>>>'
@@ -34,11 +34,12 @@ prechigh
left '.'
right INDENT
left OUTDENT
right WHEN LEADING_WHEN IN BY
right WHEN LEADING_WHEN IN INO BY
right THROW FOR NEW SUPER
left EXTENDS
left ASSIGN '||=' '&&='
right RETURN '=>' UNLESS IF ELSE WHILE
right RETURN
right '=>' UNLESS IF ELSE WHILE
preclow
rule
@@ -58,13 +59,13 @@ rule
| Expressions Terminator { result = val[0] }
;
# All types of expressions in our language.
# All types of expressions in our language. The basic unit of CoffeeScript
# is the expression.
Expression:
Value
| Call
| Code
| Operation
| Range
| Assign
| If
| Try
@@ -79,18 +80,20 @@ rule
| Comment
;
# A block of expressions. Note that the Rewriter will convert some postfix
# forms into blocks for us, by altering the token stream.
Block:
INDENT Expressions OUTDENT { result = val[1] }
| INDENT OUTDENT { result = Expressions.new }
;
# All tokens that can terminate an expression.
# Tokens that can terminate an expression.
Terminator:
"\n"
| ";"
;
# All hard-coded values.
# All hard-coded values. These can be printed straight to JavaScript.
Literal:
NUMBER { result = LiteralNode.new(val[0]) }
| STRING { result = LiteralNode.new(val[0]) }
@@ -107,12 +110,12 @@ rule
| OFF { result = LiteralNode.new(false) }
;
# Assignment to a variable.
# Assignment to a variable (or index).
Assign:
Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) }
;
# Assignment within an object literal.
# Assignment within an object literal (can be quoted).
AssignObj:
IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) }
| STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) }
@@ -122,6 +125,7 @@ rule
# A return statement.
Return:
RETURN Expression { result = ReturnNode.new(val[1]) }
| RETURN { result = ReturnNode.new(ValueNode.new(Value.new('null'))) }
;
# A comment.
@@ -184,8 +188,10 @@ rule
| Expression '&&=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression INSTANCEOF Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression IN Expression { result = OpNode.new(val[1], val[0], val[2]) }
;
# The existence operator.
Existence:
Expression '?' { result = ExistenceNode.new(val[0]) }
;
@@ -202,13 +208,15 @@ rule
| ParamList "," Param { result = val[0] << val[2] }
;
# A Parameter (or ParamSplat) in a function definition.
Param:
PARAM
| PARAM_SPLAT PARAM { result = ParamSplatNode.new(val[1]) }
| PARAM "." "." "." { result = ParamSplatNode.new(val[0]) }
;
# A regular splat.
Splat:
'*' Value = SPLAT { result = ArgSplatNode.new(val[1]) }
Expression "." "." "." { result = ArgSplatNode.new(val[0])}
;
# Expressions that can be treated as values.
@@ -218,6 +226,7 @@ rule
| Array { result = ValueNode.new(val[0]) }
| Object { result = ValueNode.new(val[0]) }
| Parenthetical { result = ValueNode.new(val[0]) }
| Range { result = ValueNode.new(val[0]) }
| Value Accessor { result = val[0] << val[1] }
| Invocation Accessor { result = ValueNode.new(val[0], [val[1]]) }
;
@@ -225,6 +234,7 @@ rule
# Accessing into an object or array, through dot or index notation.
Accessor:
PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) }
| PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], true) }
| Index { result = val[0] }
| Range { result = SliceNode.new(val[0]) }
;
@@ -269,6 +279,7 @@ rule
# | Invocation Code { result = val[0] << val[1] }
;
# The list of arguments to a function invocation.
Arguments:
"(" ArgList ")" { result = val[1] }
| "(" ArgList ")" Code { result = val[1] << val[3] }
@@ -330,6 +341,7 @@ rule
# The while loop. (there is no do..while).
While:
WHILE Expression Block { result = WhileNode.new(val[1], val[2]) }
| WHILE Expression { result = WhileNode.new(val[1], nil) }
;
# Array comprehensions, including guard and current index.
@@ -349,6 +361,7 @@ rule
# The source of the array comprehension can optionally be filtered.
ForSource:
IN Expression { result = {:source => val[1]} }
| INO Expression { result = {:source => val[1], :object => true} }
| ForSource
WHEN Expression { result = val[0].merge(:filter => val[2]) }
| ForSource
@@ -374,12 +387,10 @@ rule
LEADING_WHEN Expression Block { result = IfNode.new(val[1], val[2], nil, {:statement => true}) }
| LEADING_WHEN Expression Block
Terminator { result = IfNode.new(val[1], val[2], nil, {:statement => true}) }
| Comment
| Comment Terminator When { result = val[2].add_comment(val[0]) }
;
# All of the following nutso if-else destructuring is to make the
# grammar expand unambiguously.
# The most basic form of "if".
IfBlock:
IF Expression Block { result = IfNode.new(val[1], val[2]) }
;

View File

@@ -12,23 +12,23 @@ module CoffeeScript
"new", "return",
"try", "catch", "finally", "throw",
"break", "continue",
"for", "in", "by", "where", "while",
"for", "in", "ino", "by", "where", "while",
"switch", "when",
"super", "extends",
"arguments",
"delete", "instanceof", "typeof"]
# Token matching regexes.
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
IDENTIFIER = /\A([a-zA-Z$_](\w|\$)*)/
NUMBER = /\A(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i
STRING = /\A(""|''|"(.*?)[^\\]"|'(.*?)[^\\]')/m
JS = /\A(``|`(.*?)[^\\]`)/m
STRING = /\A(""|''|"(.*?)([^\\]|\\\\)"|'(.*?)([^\\]|\\\\)')/m
JS = /\A(``|`(.*?)([^\\]|\\\\)`)/m
OPERATOR = /\A([+\*&|\/\-%=<>:!]+)/
WHITESPACE = /\A([ \t]+)/
COMMENT = /\A(((\n?[ \t]*)?#.*$)+)/
CODE = /\A(=>)/
REGEX = /\A(\/(.*?)[^\\]\/[imgy]{0,4})/
MULTI_DENT = /\A((\n([ \t]*)?)+)/
REGEX = /\A(\/(.*?)([^\\]|\\\\)\/[imgy]{0,4})/
MULTI_DENT = /\A((\n([ \t]*))+)(\.)?/
LAST_DENT = /\n([ \t]*)/
ASSIGNMENT = /\A(:|=)\Z/
@@ -88,6 +88,7 @@ module CoffeeScript
tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER
tag = :LEADING_WHEN if tag == :WHEN && [:OUTDENT, :INDENT, "\n"].include?(last_tag)
@tokens[-1][0] = :PROPERTY_ACCESS if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2][1] == '.')
@tokens[-1][0] = :PROTOTYPE_ACCESS if tag == :IDENTIFIER && last_value == '::'
token(tag, identifier)
@i += identifier.length
end
@@ -139,7 +140,9 @@ module CoffeeScript
return false unless indent = @chunk[MULTI_DENT, 1]
@line += indent.scan(MULTILINER).size
@i += indent.size
return suppress_newlines(indent) if last_value.to_s.match(NO_NEWLINE) && last_value != "=>"
next_character = @chunk[MULTI_DENT, 4]
no_newlines = next_character == '.' || (last_value.to_s.match(NO_NEWLINE) && last_value != "=>")
return suppress_newlines(indent) if no_newlines
size = indent.scan(LAST_DENT).last.last.length
return newline_token(indent) if size == @indent
if size > @indent
@@ -221,8 +224,7 @@ module CoffeeScript
i -= 1
tok = @tokens[i]
return if !tok
next if tok[0] == ','
next tok[0] = :PARAM_SPLAT if tok[0] == '*'
next if ['.', ','].include?(tok[0])
return if tok[0] != :IDENTIFIER
tok[0] = :PARAM
end

View File

@@ -29,7 +29,7 @@ exports.run: args =>
while true
try
system.stdout.write('coffee> ').flush()
result: exports.evalCS(Readline.readline())
result: exports.evalCS(Readline.readline(), ['--globals'])
print(result) if result isnt undefined
catch e
print(e)
@@ -41,15 +41,15 @@ exports.compileFile: path =>
coffee.stdout.read()
# Compile a string of CoffeeScript into JavaScript.
exports.compile: source =>
coffee: OS.popen([coffeePath, "--eval", "--no-wrap"])
exports.compile: source, flags =>
coffee: OS.popen([coffeePath, "--eval", "--no-wrap"].concat(flags or []))
coffee.stdin.write(source).flush().close()
checkForErrors(coffee)
coffee.stdout.read()
# Evaluating a string of CoffeeScript first compiles it externally.
exports.evalCS: source =>
eval(exports.compile(source))
exports.evalCS: source, flags =>
eval(exports.compile(source, flags))
# Make a factory for the CoffeeScript environment.
exports.makeNarwhalFactory: path =>

View File

@@ -20,25 +20,24 @@
// Run a simple REPL, round-tripping to the CoffeeScript compiler for every
// command.
exports.run = function run(args) {
var __a, __b, __c, i, path, result;
var __a, __b, i, result;
if (args.length) {
__a = args;
__b = [];
for (i in __a) {
if (__a.hasOwnProperty(i)) {
path = __a[i];
exports.evalCS(File.read(path));
__c = delete args[i];
__b.push(__c);
}
__b = function(path, i) {
exports.evalCS(File.read(path));
delete args[i];
};
if (__a instanceof Array) {
for (i=0; i<__a.length; i++) __b(__a[i], i);
} else {
for (i in __a) { if (__a.hasOwnProperty(i)) __b(__a[i], i); }
}
__b;
return true;
}
while (true) {
try {
system.stdout.write('coffee> ').flush();
result = exports.evalCS(Readline.readline());
result = exports.evalCS(Readline.readline(), ['--globals']);
if (result !== undefined) {
print(result);
}
@@ -46,6 +45,7 @@
print(e);
}
}
return null;
};
// Compile a given CoffeeScript file into JavaScript.
exports.compileFile = function compileFile(path) {
@@ -55,16 +55,16 @@
return coffee.stdout.read();
};
// Compile a string of CoffeeScript into JavaScript.
exports.compile = function compile(source) {
exports.compile = function compile(source, flags) {
var coffee;
coffee = OS.popen([coffeePath, "--eval", "--no-wrap"]);
coffee = OS.popen([coffeePath, "--eval", "--no-wrap"].concat(flags || []));
coffee.stdin.write(source).flush().close();
checkForErrors(coffee);
return coffee.stdout.read();
};
// Evaluating a string of CoffeeScript first compiles it externally.
exports.evalCS = function evalCS(source) {
return eval(exports.compile(source));
exports.evalCS = function evalCS(source, flags) {
return eval(exports.compile(source, flags));
};
// Make a factory for the CoffeeScript environment.
exports.makeNarwhalFactory = function makeNarwhalFactory(path) {

View File

@@ -8,9 +8,9 @@
// Reload the coffee-script environment from source.
reload: function reload(topId, path) {
coffeescript = coffeescript || require('coffee-script');
return (factories[topId] = function() {
return factories[topId] = function() {
return coffeescript.makeNarwhalFactory(path);
});
};
},
// Ensure that the coffee-script environment is loaded.
load: function load(topId, path) {

View File

@@ -29,6 +29,7 @@ module CoffeeScript
# already been asked to return the result.
def compile(o={})
@options = o.dup
@indent = o[:indent]
top = self.is_a?(ForNode) ? @options[:top] : @options.delete(:top)
closure = statement? && !statement_only? && !top && !@options[:return]
closure ? compile_closure(@options) : compile_node(@options)
@@ -36,10 +37,15 @@ module CoffeeScript
def compile_closure(o={})
indent = o[:indent]
o[:indent] += TAB
@indent = (o[:indent] = idt(1))
"(function() {\n#{compile_node(o.merge(:return => true))}\n#{indent}})()"
end
# Quick method for the current indentation level, plus tabs out.
def idt(tabs=0)
@indent + (TAB * tabs)
end
# Default implementations of the common node methods.
def unwrap; self; end
def statement?; false; end
@@ -95,16 +101,22 @@ module CoffeeScript
def compile_node(options={})
compiled = @expressions.map do |node|
o = options.dup
@indent = o[:indent]
returns = o.delete(:return)
if last?(node) && returns && !node.statement_only?
if node.statement?
node.compile(o.merge(:return => true))
else
"#{o[:indent]}return #{node.compile(o)};"
if o[:top] && o[:last_assign] && o[:last_assign][0..0][/[A-Z]/]
temp = o[:scope].free_variable
"#{idt}#{temp} = #{node.compile(o)};\n#{idt}return #{o[:last_assign]} === this.constructor ? this : #{temp};"
else
"#{idt}return #{node.compile(o)};"
end
end
else
ending = node.statement? ? '' : ';'
indent = node.statement? ? '' : o[:indent]
indent = node.statement? ? '' : idt
"#{indent}#{node.compile(o.merge(:top => true))}#{ending}"
end
end
@@ -114,8 +126,9 @@ module CoffeeScript
# If this is the top-level Expressions, wrap everything in a safety closure.
def compile_root(o={})
indent = o[:no_wrap] ? '' : TAB
@indent = indent
o.merge!(:indent => indent, :scope => Scope.new(nil, self))
code = o[:no_wrap] ? compile_node(o) : compile_with_declarations(o)
code = o[:globals] ? compile_node(o) : compile_with_declarations(o)
code.gsub!(STRIP_TRAILING_WHITESPACE, '')
o[:no_wrap] ? code : "(function(){\n#{code}\n})();"
end
@@ -123,7 +136,7 @@ module CoffeeScript
def compile_with_declarations(o={})
code = compile_node(o)
decls = ''
decls = "#{o[:indent]}var #{o[:scope].declared_variables.join(', ')};\n" if o[:scope].declarations?(self)
decls = "#{idt}var #{o[:scope].declared_variables.join(', ')};\n" if o[:scope].declarations?(self)
decls + code
end
@@ -140,6 +153,10 @@ module CoffeeScript
attr_reader :value
def self.wrap(string)
self.new(Value.new(string))
end
def initialize(value)
@value = value
end
@@ -151,7 +168,7 @@ module CoffeeScript
def compile_node(o)
val = CONVERSIONS[@value.to_s] || @value.to_s
indent = statement? ? o[:indent] : ''
indent = statement? ? idt : ''
ending = statement? ? ';' : ''
write("#{indent}#{val}#{ending}")
end
@@ -170,7 +187,7 @@ module CoffeeScript
def compile_node(o)
return write(@expression.compile(o.merge(:return => true))) if @expression.statement?
compiled = @expression.compile(o)
write(@expression.statement? ? "#{compiled}\n#{o[:indent]}return null;" : "#{o[:indent]}return #{compiled};")
write(@expression.statement? ? "#{compiled}\n#{idt}return null;" : "#{idt}return #{compiled};")
end
end
@@ -184,7 +201,7 @@ module CoffeeScript
end
def compile_node(o={})
delimiter = "\n#{o[:indent]}//"
delimiter = "\n#{idt}//"
comment = "#{delimiter}#{@lines.join(delimiter)}"
write(comment)
end
@@ -231,7 +248,9 @@ module CoffeeScript
def compile_super(args, o)
methname = o[:last_assign]
arg_part = args.empty? ? '' : ", #{args}"
"#{o[:proto_assign]}.__superClass__.#{methname}.call(this#{arg_part})"
meth = o[:proto_assign] ? "#{o[:proto_assign]}.__superClass__.#{methname}" :
"#{methname}.__superClass__.constructor"
"#{meth}.call(this#{arg_part})"
end
def compile_splat(o)
@@ -257,9 +276,12 @@ module CoffeeScript
end
def compile_node(o={})
constructor = o[:scope].free_variable
sub, sup = @sub_object.compile(o), @super_object.compile(o)
"#{o[:indent]}#{sub}.__superClass__ = #{sup}.prototype;\n#{o[:indent]}" +
"#{sub}.prototype = new #{sup}();\n#{o[:indent]}" +
"#{idt}#{constructor} = function(){};\n#{idt}" +
"#{constructor}.prototype = #{sup}.prototype;\n#{idt}" +
"#{sub}.__superClass__ = #{sup}.prototype;\n#{idt}" +
"#{sub}.prototype = new #{constructor}();\n#{idt}" +
"#{sub}.prototype.constructor = #{sub};"
end
@@ -302,12 +324,13 @@ module CoffeeScript
class AccessorNode < Node
attr_reader :name
def initialize(name)
@name = name
def initialize(name, prototype=false)
@name, @prototype = name, prototype
end
def compile_node(o)
write(".#{@name}")
proto = @prototype ? "prototype." : ''
write(".#{proto}#{@name}")
end
end
@@ -346,15 +369,15 @@ module CoffeeScript
end
def compile_variables(o)
idt = o[:indent]
@indent = o[:indent]
@from_var, @to_var = o[:scope].free_variable, o[:scope].free_variable
from_val, to_val = @from.compile(o), @to.compile(o)
write("#{idt}#{@from_var} = #{from_val};\n#{idt}#{@to_var} = #{to_val};\n#{idt}")
write("#{@from_var} = #{from_val}; #{@to_var} = #{to_val};\n#{idt}")
end
def compile_node(o)
idx, step = o.delete(:index), o.delete(:step)
raise SyntaxError, "unexpected range literal" unless idx
return compile_array(o) unless idx
vars = "#{idx}=#{@from_var}"
step = step ? step.compile(o) : '1'
compare = "(#{@from_var} <= #{@to_var} ? #{idx} #{less_operator} #{@to_var} : #{idx} #{greater_operator} #{@to_var})"
@@ -362,6 +385,15 @@ module CoffeeScript
write("#{vars}; #{compare}; #{incr}")
end
# Expand the range into the equivalent array, if it's not being used as
# part of a comprehension, slice, or splice.
# TODO: This generates pretty ugly code ... shrink it.
def compile_array(o)
body = Expressions.wrap(LiteralNode.wrap('i'))
arr = Expressions.wrap(ForNode.new(body, {:source => ValueNode.new(self)}, Value.new('i')))
ParentheticalNode.new(CallNode.new(CodeNode.new([], arr))).compile(o)
end
end
# An array slice literal. Unlike JavaScript's Array#slice, the second parameter
@@ -385,7 +417,7 @@ module CoffeeScript
# Setting the value of a local variable, or the value of an object property.
class AssignNode < Node
PROTO_ASSIGN = /\A(\S+)\.prototype/
LEADING_DOT = /\A\./
LEADING_DOT = /\A\.(prototype\.)?/
attr_reader :variable, :value, :context
@@ -403,7 +435,7 @@ module CoffeeScript
return write("#{name}: #{@value.compile(o)}") if @context == :object
o[:scope].find(name) unless @variable.properties?
val = "#{name} = #{@value.compile(o)}"
write(o[:return] ? "#{o[:indent]}return (#{val})" : val)
write(o[:return] ? "#{idt}return (#{val})" : val)
end
def compile_splice(o)
@@ -473,12 +505,12 @@ module CoffeeScript
def compile_node(o)
shared_scope = o.delete(:shared_scope)
indent = o[:indent]
o[:scope] = shared_scope || Scope.new(o[:scope], @body)
o[:return] = true
o[:top] = true
o[:indent] += TAB
o[:indent] = idt(1)
o.delete(:no_wrap)
o.delete(:globals)
name = o.delete(:immediate_assign)
if @params.last.is_a?(ParamSplatNode)
splat = @params.pop
@@ -488,7 +520,7 @@ module CoffeeScript
@params.each {|id| o[:scope].parameter(id.to_s) }
code = @body.compile_with_declarations(o)
name_part = name ? " #{name}" : ''
write("function#{name_part}(#{@params.join(', ')}) {\n#{code}\n#{indent}}")
write("function#{name_part}(#{@params.join(', ')}) {\n#{code}\n#{idt}}")
end
end
@@ -532,18 +564,17 @@ module CoffeeScript
# AssignNodes get interleaved correctly, with no trailing commas or
# commas affixed to comments. TODO: Extract this and add it to ArrayNode.
def compile_node(o)
indent = o[:indent]
o[:indent] += TAB
o[:indent] = idt(1)
joins = Hash.new("\n")
non_comments = @properties.select {|p| !p.is_a?(CommentNode) }
non_comments.each {|p| joins[p] = p == non_comments.last ? "\n" : ",\n" }
props = @properties.map { |prop|
join = joins[prop]
join = '' if prop == @properties.last
idt = prop.is_a?(CommentNode) ? '' : o[:indent]
"#{idt}#{prop.compile(o)}#{join}"
indent = prop.is_a?(CommentNode) ? '' : idt(1)
"#{indent}#{prop.compile(o)}#{join}"
}.join('')
write("{\n#{props}\n#{indent}}")
write("{\n#{props}\n#{idt}}")
end
end
@@ -556,14 +587,13 @@ module CoffeeScript
end
def compile_node(o)
indent = o[:indent]
o[:indent] += TAB
o[:indent] = idt(1)
objects = @objects.map { |obj|
code = obj.compile(o)
obj.is_a?(CommentNode) ? "\n#{code}\n#{o[:indent]}" :
obj == @objects.last ? code : "#{code}, "
}.join('')
ending = objects.include?("\n") ? "\n#{indent}]" : ']'
ending = objects.include?("\n") ? "\n#{idt}]" : ']'
write("[#{objects}#{ending}")
end
end
@@ -581,12 +611,12 @@ module CoffeeScript
def compile_node(o)
returns = o.delete(:return)
indent = o[:indent]
o[:indent] += TAB
o[:indent] = idt(1)
o[:top] = true
cond = @condition.compile(o)
post = returns ? "\n#{indent}return null;" : ''
write("#{indent}while (#{cond}) {\n#{@body.compile(o)}\n#{indent}}#{post}")
post = returns ? "\n#{idt}return null;" : ''
return write("#{idt}while (#{cond}) null;#{post}") if @body.nil?
write("#{idt}while (#{cond}) {\n#{@body.compile(o)}\n#{idt}}#{post}")
end
end
@@ -604,56 +634,63 @@ module CoffeeScript
@source = source[:source]
@filter = source[:filter]
@step = source[:step]
@object = !!source[:object]
@name, @index = @index, @name if @object
end
def compile_node(o)
top_level = o.delete(:top) && !o[:return]
range = @source.is_a?(RangeNode)
range = @source.is_a?(ValueNode) && @source.literal.is_a?(RangeNode) && @source.properties.empty?
source = range ? @source.literal : @source
scope = o[:scope]
name_found = scope.find(@name)
name_found = @name && scope.find(@name)
index_found = @index && scope.find(@index)
body_dent = idt(1)
svar = scope.free_variable
ivar = range ? name : @index ? @index : scope.free_variable
rvar = scope.free_variable unless top_level
tvar = scope.free_variable
if range
body_dent = o[:indent] + TAB
var_part, pre_cond, post_cond = '', '', ''
index_var = scope.free_variable
source_part = @source.compile_variables(o)
for_part = "#{index_var}=0, #{@source.compile(o.merge(:index => ivar, :step => @step))}, #{index_var}++"
source_part = source.compile_variables(o)
for_part = "#{index_var}=0, #{source.compile(o.merge(:index => ivar, :step => @step))}, #{index_var}++"
var_part = ''
else
index_var = nil
body_dent = o[:indent] + TAB + TAB
source_part = "#{o[:indent]}#{svar} = #{@source.compile(o)};\n#{o[:indent]}"
for_part = "#{ivar} in #{svar}"
pre_cond = "\n#{o[:indent] + TAB}if (#{svar}.hasOwnProperty(#{ivar})) {"
var_part = "\n#{body_dent}#{@name} = #{svar}[#{ivar}];"
post_cond = "\n#{o[:indent] + TAB}}"
source_part = "#{svar} = #{source.compile(o)};\n#{idt}"
for_part = "#{ivar}=0; #{ivar}<#{svar}.length; #{ivar}++"
for_part = "#{ivar} in #{svar}" if @object
var_part = @name ? "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" : ''
end
body = @body
set_result = rvar ? "#{rvar} = [];\n#{o[:indent]}" : ''
set_result = rvar ? "#{idt}#{rvar} = []; " : idt
return_result = rvar || ''
temp_var = ValueNode.new(LiteralNode.new(tvar))
if top_level
body = Expressions.wrap(body)
else
body = Expressions.wrap(
AssignNode.new(temp_var, @body.unwrap),
CallNode.new(ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [temp_var])
)
body = Expressions.wrap(CallNode.new(
ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [body.unwrap]
))
end
if o[:return]
return_result = "return #{return_result}" if o[:return]
o.delete(:return)
body = IfNode.new(@filter, body, nil, :statement => true) if @filter
elsif @filter
body = Expressions.wrap(IfNode.new(@filter, @body))
body = Expressions.wrap(IfNode.new(@filter, body))
end
if @object
body = Expressions.wrap(IfNode.new(
CallNode.new(ValueNode.new(LiteralNode.wrap(svar), [AccessorNode.new(Value.new('hasOwnProperty'))]), [LiteralNode.wrap(ivar)]),
Expressions.wrap(body),
nil,
{:statement => true}
))
end
return_result = "\n#{o[:indent]}#{return_result};" unless top_level
return_result = "\n#{idt}#{return_result};" unless top_level
body = body.compile(o.merge(:indent => body_dent, :top => true))
write("#{source_part}#{set_result}for (#{for_part}) {#{pre_cond}#{var_part}\n#{body}#{post_cond}\n#{o[:indent]}}#{return_result}")
vars = range ? @name : "#{@name}, #{ivar}"
return write(set_result + source_part + "for (#{for_part}) {\n#{var_part}#{body}\n#{idt}}\n#{idt}#{return_result}")
end
end
@@ -668,13 +705,12 @@ module CoffeeScript
end
def compile_node(o)
indent = o[:indent]
o[:indent] += TAB
o[:indent] = idt(1)
o[:top] = true
error_part = @error ? " (#{@error}) " : ' '
catch_part = @recovery && " catch#{error_part}{\n#{@recovery.compile(o)}\n#{indent}}"
finally_part = @finally && " finally {\n#{@finally.compile(o.merge(:return => nil))}\n#{indent}}"
write("#{indent}try {\n#{@try.compile(o)}\n#{indent}}#{catch_part}#{finally_part}")
catch_part = @recovery && " catch#{error_part}{\n#{@recovery.compile(o)}\n#{idt}}"
finally_part = @finally && " finally {\n#{@finally.compile(o.merge(:return => nil))}\n#{idt}}"
write("#{idt}try {\n#{@try.compile(o)}\n#{idt}}#{catch_part}#{finally_part}")
end
end
@@ -689,7 +725,7 @@ module CoffeeScript
end
def compile_node(o)
write("#{o[:indent]}throw #{@expression.compile(o)};")
write("#{idt}throw #{@expression.compile(o)};")
end
end
@@ -746,6 +782,11 @@ module CoffeeScript
self
end
def add_comment(comment)
@comment = comment
self
end
def force_statement
@tags[:statement] = true
self
@@ -772,7 +813,7 @@ module CoffeeScript
# The IfNode only compiles into a statement if either of the bodies needs
# to be a statement.
def statement?
@is_statement ||= !!(@tags[:statement] || @body.statement? || (@else_body && @else_body.statement?))
@is_statement ||= !!(@comment || @tags[:statement] || @body.statement? || (@else_body && @else_body.statement?))
end
def compile_node(o)
@@ -782,18 +823,19 @@ module CoffeeScript
# Compile the IfNode as a regular if-else statement. Flattened chains
# force sub-else bodies into statement form.
def compile_statement(o)
indent = o[:indent]
child = o.delete(:chain_child)
cond_o = o.dup
child = o.delete(:chain_child)
cond_o = o.dup
cond_o.delete(:return)
o[:indent] += TAB
o[:top] = true
if_dent = child ? '' : indent
if_part = "#{if_dent}if (#{@condition.compile(cond_o)}) {\n#{Expressions.wrap(@body).compile(o)}\n#{indent}}"
o[:indent] = idt(1)
o[:top] = true
if_dent = child ? '' : idt
com_dent = child ? idt : ''
prefix = @comment ? @comment.compile(cond_o) + "\n#{com_dent}" : ''
if_part = "#{prefix}#{if_dent}if (#{@condition.compile(cond_o)}) {\n#{Expressions.wrap(@body).compile(o)}\n#{idt}}"
return if_part unless @else_body
else_part = chain? ?
" else #{@else_body.compile(o.merge(:indent => indent, :chain_child => true))}" :
" else {\n#{Expressions.wrap(@else_body).compile(o)}\n#{indent}}"
" else #{@else_body.compile(o.merge(:indent => idt, :chain_child => true))}" :
" else {\n#{Expressions.wrap(@else_body).compile(o)}\n#{idt}}"
if_part + else_part
end

File diff suppressed because it is too large Load Diff

View File

@@ -69,6 +69,10 @@ module CoffeeScript
@tokens.delete_at(i + 2)
@tokens.delete_at(i - 2)
next 0
elsif prev[0] == "\n" && [:INDENT, :OUTDENT].include?(after[0])
@tokens.delete_at(i + 2)
@tokens[i - 1] = after
next 1
elsif !["\n", :INDENT, :OUTDENT].include?(prev[0])
@tokens.insert(i, ["\n", Value.new("\n", token[1].line)])
next 2

View File

@@ -5,7 +5,7 @@ module CoffeeScript
class Value
attr_reader :value, :line
def initialize(value, line)
def initialize(value, line=nil)
@value, @line = value, line
end

View File

@@ -5,5 +5,5 @@
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language"],
"author": "Jeremy Ashkenas",
"version": "0.2.1"
"version": "0.2.2"
}

View File

@@ -5,11 +5,11 @@ print(results.join(',') is '2,18')
obj: {one: 1, two: 2, three: 3}
names: key + '!' for value, key in obj
odds: key + '!' for value, key in obj when value % 2 isnt 0
names: key + '!' for key ino obj
odds: key + '!' for key, value ino obj when value % 2 isnt 0
print(names.join(' ') is "one! two! three!")
print(odds.join(' ') is "one! three!")
print(names.join(' ') is "one! two! three!")
print(odds.join(' ') is "one! three!")
evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
@@ -19,3 +19,7 @@ evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
print(evens.join(', ') is '4, 6, 8')
# Make sure that the "in" operator still works.
print(2 in evens)

View File

@@ -1,23 +1,38 @@
Base: =>
Base.prototype.func: string =>
Base::func: string =>
'zero/' + string
FirstChild: =>
FirstChild extends Base
FirstChild.prototype.func: string =>
FirstChild::func: string =>
super('one/') + string
SecondChild: =>
SecondChild extends FirstChild
SecondChild.prototype.func: string =>
SecondChild::func: string =>
super('two/') + string
ThirdChild: =>
this.array: [1, 2, 3]
ThirdChild extends SecondChild
ThirdChild.prototype.func: string =>
ThirdChild::func: string =>
super('three/') + string
result: (new ThirdChild()).func('four')
print(result is 'zero/one/two/three/four')
TopClass: arg =>
this.prop: 'top-' + arg
SuperClass: arg =>
super('super-' + arg)
SubClass: =>
super('sub')
SuperClass extends TopClass
SubClass extends SuperClass
print((new SubClass()).prop is 'top-super-sub')

View File

@@ -2,4 +2,23 @@ identity_wrap: x => => x
result: identity_wrap(identity_wrap(true))()()
print(result)
print(result)
str: 'god'
result: str.
split('').
reverse().
reverse().
reverse()
print(result.join('') is 'dog')
result: str
.split('')
.reverse()
.reverse()
.reverse()
print(result.join('') is 'dog')

View File

@@ -1,8 +1,17 @@
# comment
func: =>
# comment
false
false # comment
false
# comment
true
print(func())
switch 'string'
# comment
when false then something()
# comment
when null
something_else()
print(func())

View File

@@ -11,4 +11,27 @@ print(!!words.match(regex))
neg: (3 -4)
print(neg is -1)
print(neg is -1)
func: =>
return if true
print(func() is null)
str: "\\"
reg: /\\/
print(reg(str) and str is '\\')
i: 10
while i -= 1
print(i is 0)
money$: 'dollars'
print(money$ is 'dollars')

View File

@@ -5,4 +5,7 @@ b: array[2...4]
result: a.concat(b).join(' ')
print(result is "7 8 9 2 3")
print(result is "7 8 9 2 3")
countdown: [10..1].join(' ')
print(countdown is "10 9 8 7 6 5 4 3 2 1")

View File

@@ -1,4 +1,4 @@
func: first, second, *rest =>
func: first, second, rest... =>
rest.join(' ')
result: func(1, 2, 3, 4, 5)
@@ -8,7 +8,7 @@ print(result is "3 4 5")
gold: silver: bronze: the_field: null
medalists: first, second, third, *rest =>
medalists: first, second, third, rest... =>
gold: first
silver: second
bronze: third
@@ -27,7 +27,7 @@ contenders: [
"Usain Bolt"
]
medalists("Mighty Mouse", *contenders)
medalists("Mighty Mouse", contenders...)
print(gold is "Mighty Mouse")
print(silver is "Michael Phelps")

View File

@@ -7,7 +7,11 @@ result: switch num
true
false
when 10 then true
# Mid-switch comment with whitespace
# and multi line
when 11 then false
else false
print(result)

View File

@@ -1,35 +0,0 @@
(function(){
// The cornerstone, an each implementation.
// Handles objects implementing forEach, arrays, and raw objects.
_.each = function each(obj, iterator, context) {
var __a, __b, __c, __d, __e, i, index, item, key;
index = 0;
try {
if (obj.forEach) {
obj.forEach(iterator, context);
} else if (_.isArray(obj) || _.isArguments(obj)) {
__a = obj;
for (i in __a) {
if (__a.hasOwnProperty(i)) {
item = __a[i];
iterator.call(context, item, i, obj);
}
}
} else {
__c = _.keys(obj);
for (__d in __c) {
if (__c.hasOwnProperty(__d)) {
key = __c[__d];
iterator.call(context, obj[key], key, obj);
}
}
}
} catch (e) {
if (e !== breaker) {
throw e;
}
}
return obj;
};
})();

View File

@@ -1,33 +0,0 @@
// The cornerstone, an each implementation.
// Handles objects implementing forEach, arrays, and raw objects.
_.each = function each(obj, iterator, context) {
var __a, __b, __c, __d, __e, i, index, item, key;
index = 0;
try {
if (obj.forEach) {
obj.forEach(iterator, context);
} else if (_.isArray(obj) || _.isArguments(obj)) {
__a = obj;
for (i in __a) {
if (__a.hasOwnProperty(i)) {
item = __a[i];
iterator.call(context, item, i, obj);
}
}
} else {
__c = _.keys(obj);
for (__d in __c) {
if (__c.hasOwnProperty(__d)) {
key = __c[__d];
iterator.call(context, obj[key], key, obj);
}
}
}
} catch (e) {
if (e !== breaker) {
throw e;
}
}
return obj;
};

View File

@@ -69,12 +69,6 @@ class ParserTest < Test::Unit::TestCase
assert assign.variable.literal == '_'
assert assign.value.is_a?(CodeNode)
assert assign.value.params == ['obj', 'iterator', 'context']
assert nodes.compile == File.read('test/fixtures/generation/each.js')
end
def test_no_wrap
nodes = @par.parse(File.read('test/fixtures/generation/each.coffee'))
assert nodes.compile(:no_wrap => true) == File.read('test/fixtures/generation/each_no_wrap.js')
end
end