diff --git a/.gitignore b/.gitignore index 115973f647..5381d48f23 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ presentation test.coffee parser.output -lib/coffee_script/parser.rb test/fixtures/underscore examples/beautiful_code/parse.coffee *.gem \ No newline at end of file diff --git a/Rakefile b/Rakefile index 8409bfad28..ce2a0b9783 100644 --- a/Rakefile +++ b/Rakefile @@ -25,7 +25,7 @@ namespace :build do desc "Compile and install the Ultraviolet syntax highlighter" task :ultraviolet do - sh "plist2syntax lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage" + sh "plist2syntax extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage" sh "sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax" end @@ -58,6 +58,8 @@ namespace :gem do desc 'Build and install the coffee-script gem' task :install do + verbose = "lib/coffee_script/parser.output" + FileUtils.rm(verbose) if File.exists?(verbose) sh "gem build coffee-script.gemspec" sh "sudo gem install #{Dir['*.gem'].join(' ')} --local --no-ri --no-rdoc" end diff --git a/coffee-script.gemspec b/coffee-script.gemspec index df04ad5e5f..8fdf3e5341 100644 --- a/coffee-script.gemspec +++ b/coffee-script.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.name = 'coffee-script' - s.version = '0.2.6' # Keep version in sync with coffee-script.rb - s.date = '2010-1-17' + s.version = '0.3.0' # Keep version in sync with coffee-script.rb + s.date = '2010-1-26' s.homepage = "http://jashkenas.github.com/coffee-script/" s.summary = "The CoffeeScript Compiler" @@ -22,5 +22,6 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.executables = ['coffee'] - s.files = Dir['bin/*', 'examples/*', 'lib/**/*', 'coffee-script.gemspec', 'LICENSE', 'README', 'package.json'] + s.files = Dir['bin/*', 'examples/*', 'extras/**/*', 'lib/**/*', + 'coffee-script.gemspec', 'LICENSE', 'README', 'package.json'] end \ No newline at end of file diff --git a/documentation/coffee/arguments.coffee b/documentation/coffee/arguments.coffee index fd4f2fbaee..ac548c127b 100644 --- a/documentation/coffee/arguments.coffee +++ b/documentation/coffee/arguments.coffee @@ -1,4 +1,4 @@ -backwards: => - alert(arguments.reverse()) +backwards: -> + alert arguments.reverse() -backwards("stairway", "to", "heaven") \ No newline at end of file +backwards "stairway", "to", "heaven" \ No newline at end of file diff --git a/documentation/coffee/array_comprehensions.coffee b/documentation/coffee/array_comprehensions.coffee index 3510e1fb0a..2a90a136e7 100644 --- a/documentation/coffee/array_comprehensions.coffee +++ b/documentation/coffee/array_comprehensions.coffee @@ -4,4 +4,4 @@ lunch: eat(food) for food in ['toast', 'cheese', 'wine'] # Naive collision detection. for roid in asteroids for roid2 in asteroids when roid isnt roid2 - roid.explode() if roid.overlaps(roid2) \ No newline at end of file + roid.explode() if roid.overlaps roid2 \ No newline at end of file diff --git a/documentation/coffee/blocks.coffee b/documentation/coffee/blocks.coffee deleted file mode 100644 index 6f31ee164c..0000000000 --- a/documentation/coffee/blocks.coffee +++ /dev/null @@ -1,4 +0,0 @@ -$('table.list').each() table => - $('tr.account', table).each() row => - row.show() - row.highlight() diff --git a/documentation/coffee/expressions.coffee b/documentation/coffee/expressions.coffee index fa0c1e3af4..74a02466df 100644 --- a/documentation/coffee/expressions.coffee +++ b/documentation/coffee/expressions.coffee @@ -1,4 +1,4 @@ -grade: student => +grade: (student) -> if student.excellent_work "A+" else if student.okay_stuff diff --git a/documentation/coffee/expressions_try.coffee b/documentation/coffee/expressions_try.coffee index 7b635287db..13fdfec201 100644 --- a/documentation/coffee/expressions_try.coffee +++ b/documentation/coffee/expressions_try.coffee @@ -2,5 +2,5 @@ alert( try nonexistent / undefined catch error - "Caught an error: " + error + "And the error is ... " + error ) \ No newline at end of file diff --git a/documentation/coffee/fat_arrow.coffee b/documentation/coffee/fat_arrow.coffee new file mode 100644 index 0000000000..4b7759d37f --- /dev/null +++ b/documentation/coffee/fat_arrow.coffee @@ -0,0 +1,6 @@ +Account: (customer, cart) -> + this.customer: customer + this.cart: cart + + $('.shopping_cart').bind 'click', (event) => + this.customer.purchase this.cart \ No newline at end of file diff --git a/documentation/coffee/functions.coffee b/documentation/coffee/functions.coffee index ccc9401df5..4fd48d32f7 100644 --- a/documentation/coffee/functions.coffee +++ b/documentation/coffee/functions.coffee @@ -1,2 +1,2 @@ -square: x => x * x -cube: x => square(x) * x +square: (x) -> x * x +cube: (x) -> square(x) * x diff --git a/documentation/coffee/long_arrow.coffee b/documentation/coffee/long_arrow.coffee deleted file mode 100644 index 86c64e9be4..0000000000 --- a/documentation/coffee/long_arrow.coffee +++ /dev/null @@ -1,6 +0,0 @@ -Account: customer, cart => - this.customer: customer - this.cart: cart - - $('.shopping_cart').bind('click') event ==> - this.customer.purchase(this.cart) \ No newline at end of file diff --git a/documentation/coffee/multiple_return_values.coffee b/documentation/coffee/multiple_return_values.coffee index d175cc8043..3fe572b1d9 100644 --- a/documentation/coffee/multiple_return_values.coffee +++ b/documentation/coffee/multiple_return_values.coffee @@ -1,5 +1,5 @@ -weather_report: location => +weather_report: (location) -> # Make an Ajax request to fetch the weather... [location, 72, "Mostly Sunny"] -[city, temp, forecast]: weather_report("Berkeley, CA") \ No newline at end of file +[city, temp, forecast]: weather_report "Berkeley, CA" \ No newline at end of file diff --git a/documentation/coffee/overview.coffee b/documentation/coffee/overview.coffee index 6c940d9fd2..23bdb4bd85 100644 --- a/documentation/coffee/overview.coffee +++ b/documentation/coffee/overview.coffee @@ -6,7 +6,7 @@ opposite_day: true number: -42 if opposite_day # Functions: -square: x => x * x +square: (x) -> x * x # Arrays: list: [1, 2, 3, 4, 5] @@ -15,15 +15,15 @@ list: [1, 2, 3, 4, 5] math: { root: Math.sqrt square: square - cube: x => x * square(x) + cube: (x) -> x * square x } # Splats: -race: winner, runners... => - print(winner, runners) +race: (winner, runners...) -> + print winner, runners # Existence: -alert("I knew it!") if elvis? +alert "I knew it!" if elvis? # Array comprehensions: -cubed_list: math.cube(num) for num in list +cubed_list: math.cube num for num in list diff --git a/documentation/coffee/range_comprehensions.coffee b/documentation/coffee/range_comprehensions.coffee index 63ee92e2e2..33790f5a29 100644 --- a/documentation/coffee/range_comprehensions.coffee +++ b/documentation/coffee/range_comprehensions.coffee @@ -1,6 +1,6 @@ countdown: num for num in [10..1] -egg_delivery: => +egg_delivery: -> for i in [0...eggs.length] by 12 dozen_eggs: eggs[i...i+12] - deliver(new egg_carton(dozen)) + deliver new egg_carton(dozen) diff --git a/documentation/coffee/scope.coffee b/documentation/coffee/scope.coffee index b074dad293..30eedacf8a 100644 --- a/documentation/coffee/scope.coffee +++ b/documentation/coffee/scope.coffee @@ -1,5 +1,5 @@ num: 1 -change_numbers: => +change_numbers: -> new_num: -1 num: 10 new_num: change_numbers() \ No newline at end of file diff --git a/documentation/coffee/soaks.coffee b/documentation/coffee/soaks.coffee new file mode 100644 index 0000000000..964fef5b72 --- /dev/null +++ b/documentation/coffee/soaks.coffee @@ -0,0 +1 @@ +lottery.draw_winner()?.address?.zipcode diff --git a/documentation/coffee/splats.coffee b/documentation/coffee/splats.coffee index 035b902f51..9faf40155e 100644 --- a/documentation/coffee/splats.coffee +++ b/documentation/coffee/splats.coffee @@ -1,6 +1,6 @@ gold: silver: the_field: "unknown" -medalists: first, second, rest... => +award_medals: (first, second, rest...) -> gold: first silver: second the_field: rest @@ -18,8 +18,8 @@ contenders: [ "Usain Bolt" ] -medalists(contenders...) +award_medals contenders... -alert("Gold: " + gold) -alert("Silver: " + silver) -alert("The Field: " + the_field) \ No newline at end of file +alert "Gold: " + gold +alert "Silver: " + silver +alert "The Field: " + the_field \ No newline at end of file diff --git a/documentation/coffee/super.coffee b/documentation/coffee/super.coffee index a64eff39b2..b45faff0ff 100644 --- a/documentation/coffee/super.coffee +++ b/documentation/coffee/super.coffee @@ -1,21 +1,21 @@ -Animal: => -Animal::move: meters => - alert(this.name + " moved " + meters + "m.") +Animal: -> +Animal::move: (meters) -> + alert this.name + " moved " + meters + "m." -Snake: name => this.name: name +Snake: (name) -> this.name: name Snake extends Animal -Snake::move: => - alert("Slithering...") - super(5) +Snake::move: -> + alert "Slithering..." + super 5 -Horse: name => this.name: name +Horse: (name) -> this.name: name Horse extends Animal -Horse::move: => - alert("Galloping...") - super(45) +Horse::move: -> + alert "Galloping..." + super 45 -sam: new Snake("Sammy the Python") -tom: new Horse("Tommy the Palomino") +sam: new Snake "Sammy the Python" +tom: new Horse "Tommy the Palomino" sam.move() tom.move() diff --git a/documentation/coffee/try.coffee b/documentation/coffee/try.coffee index 169df020af..67f4d19763 100644 --- a/documentation/coffee/try.coffee +++ b/documentation/coffee/try.coffee @@ -2,6 +2,6 @@ try all_hell_breaks_loose() cats_and_dogs_living_together() catch error - print(error) + print error finally clean_up() \ No newline at end of file diff --git a/documentation/coffee/while.coffee b/documentation/coffee/while.coffee index 625e6ed6a1..0d2b3a21da 100644 --- a/documentation/coffee/while.coffee +++ b/documentation/coffee/while.coffee @@ -1,7 +1,9 @@ +# Econ 101 if this.studying_economics while supply > demand then buy() while supply < demand then sell() +# Nursery Rhyme num: 6 lyrics: while num -= 1 num + " little monkeys, jumping on the bed. diff --git a/documentation/css/docs.css b/documentation/css/docs.css index 1a4361f3a1..b105dd8319 100644 --- a/documentation/css/docs.css +++ b/documentation/css/docs.css @@ -6,7 +6,7 @@ body { font-family: Arial, Helvetica, sans-serif; } div.container { - width: 850px; + width: 950px; margin: 50px 0 50px 50px; } p { @@ -77,7 +77,7 @@ div.code { } div.code pre { float: left; - width: 410px; + width: 450px; border-left: 1px dotted #559; padding: 0 0 0 12px; margin: 0; diff --git a/documentation/css/idle.css b/documentation/css/idle.css index eca8faf960..23667531d3 100644 --- a/documentation/css/idle.css +++ b/documentation/css/idle.css @@ -28,6 +28,7 @@ pre.idle .LibraryConstant { color: #A535AE; } pre.idle .FunctionArgument { + color: #0076ad; } pre.idle .BuiltInConstant { color: #A535AE; diff --git a/documentation/index.html.erb b/documentation/index.html.erb index 145d2e097b..6ab260f8c0 100644 --- a/documentation/index.html.erb +++ b/documentation/index.html.erb @@ -51,7 +51,7 @@

Latest Version: - 0.2.6 + 0.3.0

Table of Contents

@@ -65,7 +65,6 @@ Objects and Arrays
Lexical Scoping and Variable Safety
Conditionals, Ternaries, and Conditional Assignment
- The Existential Operator
Aliases
Splats...
Arguments are Arrays
@@ -73,17 +72,16 @@ Comprehensions (Arrays, Objects, and Ranges)
Array Slicing and Splicing with Ranges
Everything is an Expression
+ The Existential Operator
Inheritance, and Calling Super from a Subclass
- Blocks
Pattern Matching
- Function Binding
+ Function Binding
Embedded JavaScript
Switch/When/Else
Try/Catch/Finally
Chained Comparisons
Multiline Strings and Heredocs
Resources
- Contributing
Change Log

@@ -174,7 +172,7 @@ gem install coffee-script -e, --eval Compile and print a little snippet of CoffeeScript directly from the - command line (or from stdin). For example:
coffee -e "square: x => x * x" + command line (or from stdin). For example:
coffee -e "square: (x) -> x * x" @@ -188,7 +186,7 @@ gem install coffee-script -v, --verbose As the JavaScript is being generated, print out every step of code - generation, including lexical scope and the node in the + generation, including lexical scope and the nodes in the AST. @@ -248,21 +246,27 @@ coffee --print app/scripts/*.coffee > concatenation.js use indentation.

+

+ You don't need to use parentheses to invoke a function, if you're passing + arguments:
print "coffee" +

+

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. + as long as CoffeeScript can determine that the line hasn't finished yet.

Functions and Invocation Functions are defined by a list of parameters, an arrow, and the - function body. The empty function looks like this: =>. All - functions in CoffeeScript are named by default, for the benefit of debug messages. - If you'd like to create an anonymous function, just wrap it in parentheses. + function body. The empty function looks like this: ->. All + functions in CoffeeScript are named by default, for easier debugging.

<%= code_for('functions', 'cube(5)') %> +

+ If you'd like to create an anonymous function, just wrap it in parentheses: + ((x) -> x * x) +

Assignment @@ -272,7 +276,7 @@ coffee --print app/scripts/*.coffee > concatenation.js

<%= code_for('assignment', 'greeting') %>

- Declarations of new variables are pushed up to the top of the nearest + Declaration of new variables are pushed up to the top of the nearest lexical scope, so that assignment may always be performed within expressions.

@@ -281,7 +285,7 @@ coffee --print app/scripts/*.coffee > concatenation.js Object and Array literals look very similar to their JavaScript cousins. When you spread out each assignment on a separate line, the commas are optional. In this way, assigning object properties looks the same as - assigning local variables, and can be moved around freely. You can mix + assigning local variables, and can be moved around freely. Feel free to mix and match the two styles.

<%= code_for('objects_and_arrays', 'song.join(",")') %> @@ -306,9 +310,14 @@ coffee --print app/scripts/*.coffee > concatenation.js CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult - to pollute the global namespace by accident. If you'd like to create - global variables, attach them as properties on window, - or on the exports object in CommonJS. + to pollute the global namespace by accident. +

+

+ If you'd like to create top-level variables for other scripts to use, + attach them as properties on window, or on the exports + object in CommonJS. The existential operator (below), gives you a + reliable way to figure out where to add them, if you're targeting both + CommonJS and the browser: root: exports ? this

@@ -330,20 +339,6 @@ coffee --print app/scripts/*.coffee > concatenation.js truthy variables.

-

- The Existential Operator - It's a little difficult to check for the existence of a variable in - JavaScript. if (variable) ... comes close, but fails for zero, - the empty string, and false. The existential operator ? returns true unless - a variable is null or undefined, which makes it analogous - to Ruby's nil? -

-

- It can also be used for safer conditional assignment than ||= - provides, for cases where you may be handling numbers or strings. -

- <%= code_for('existence', 'speed') %> -

Aliases Because the == operator frequently causes undesirable coercion, @@ -379,7 +374,7 @@ coffee --print app/scripts/*.coffee > concatenation.js The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, - making variable arguments a little bit more palatable. + making variable numbers of arguments a little bit more palatable.

<%= code_for('splats', true) %> @@ -481,10 +476,39 @@ coffee --print app/scripts/*.coffee > concatenation.js <%= code_for('expressions_try', true) %>

There are a handful of statements in JavaScript that can't be meaningfully - converted into expressions: break, continue, - and return. If you make use of them within a block of code, + converted into expressions, namely break, continue, + and return. If you make use of them within a block of code, CoffeeScript won't try to perform the conversion.

+ +

+ The Existential Operator + It's a little difficult to check for the existence of a variable in + JavaScript. if (variable) ... comes close, but fails for zero, + the empty string, and false. CoffeeScript's existential operator ? returns true unless + a variable is null or undefined, which makes it analogous + to Ruby's nil? +

+

+ It can also be used for safer conditional assignment than ||= + provides, for cases where you may be handling numbers or strings. +

+ <%= code_for('existence', 'speed') %> +

+ The accessor variant of the existential operator ?. can be used to soak + up null references in a chain of properties. Use it instead + of the dot accessor . in cases where the base value may be null + or undefined. If all of the properties exist then you'll get the expected + result, if the chain is broken, undefined is returned instead of + the TypeError that would be raised otherwise. +

+ <%= code_for('soaks') %> +

+ Soaking up nulls is similar to Ruby's + andand gem, and to the + safe navigation operator + in Groovy. +

Inheritance, and Calling Super from a Subclass @@ -508,20 +532,6 @@ coffee --print app/scripts/*.coffee > concatenation.js

<%= code_for('super', true) %> -

- Blocks - Many common looping functions (in Prototype, jQuery, and Underscore, - for example) take a single function as their final argument. To make - final functions easier to pass, CoffeeScript includes block syntax, - so you don't have to close the parentheses on the other side. -

- <%= code_for('blocks') %> -

- If you prefer not to use blocks, you'll need to add a pair of parentheses - to help distinguish the arguments from the definition of the function: - _.map(array, (num => num * 2)) -

-

Pattern Matching (Destructuring Assignment) To make extracting values from complex arrays and objects more convenient, @@ -544,16 +554,16 @@ coffee --print app/scripts/*.coffee > concatenation.js

<%= code_for('object_extraction', 'poet + " — " + street') %> -

+

Function binding - The long arrow ==> can be used to both define a function, and to bind + The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions - to use with bind. Functions created with the long arrow are able to access + to use with bind. Functions created with the fat arrow are able to access properties of the this where they're defined.

- <%= code_for('long_arrow') %> + <%= code_for('fat_arrow') %>

Embedded JavaScript @@ -624,6 +634,12 @@ coffee --print app/scripts/*.coffee > concatenation.js

  • Bugs, Feature Requests, and General Discussion
  • +
  • + CoffeePot
    + An implementation of CoffeeScript, written in CoffeeScript, by + Tim Caswell. Compiles just + a limited subset at this point. +
  • BistroCar
    A Rails plugin by @@ -639,39 +655,24 @@ coffee --print app/scripts/*.coffee > concatenation.js
  • -

    Contributing

    +

    Change Log

    - Here's a wish list of things that would be wonderful to have contributed: + 0.3.0 + CoffeeScript 0.3 includes major syntax changes: +
    + The function symbol was changed to + ->, and the bound function symbol is now =>. +
    + Parameter lists in function definitions must now be wrapped in parentheses. +
    + Added property soaking, with the ?. operator. +
    + Made parentheses optional, when invoking functions with arguments. +
    + Removed the obsolete block literal syntax.

    - - -

    Change Log

    -

    0.2.6 Added Python-style chained comparisons, the conditional existence diff --git a/documentation/js/array_comprehensions.js b/documentation/js/array_comprehensions.js index fae31ce941..85ca79927b 100644 --- a/documentation/js/array_comprehensions.js +++ b/documentation/js/array_comprehensions.js @@ -8,7 +8,7 @@ __a.push(eat(food)); } return __a; - })(); + }).call(this); // Naive collision detection. __d = asteroids; for (__e = 0; __e < __d.length; __e++) { diff --git a/documentation/js/blocks.js b/documentation/js/blocks.js deleted file mode 100644 index f95dd31b45..0000000000 --- a/documentation/js/blocks.js +++ /dev/null @@ -1,8 +0,0 @@ -(function(){ - $('table.list').each(function(table) { - return $('tr.account', table).each(function(row) { - row.show(); - return row.highlight(); - }); - }); -})(); \ No newline at end of file diff --git a/documentation/js/expressions_comprehension.js b/documentation/js/expressions_comprehension.js index 294c3db4ed..01d5ba45a5 100644 --- a/documentation/js/expressions_comprehension.js +++ b/documentation/js/expressions_comprehension.js @@ -10,5 +10,5 @@ } } return __a; - })()).slice(0, 10); + }).call(this)).slice(0, 10); })(); \ No newline at end of file diff --git a/documentation/js/expressions_try.js b/documentation/js/expressions_try.js index 7787cfb74e..79c77e40c7 100644 --- a/documentation/js/expressions_try.js +++ b/documentation/js/expressions_try.js @@ -3,7 +3,7 @@ try { return nonexistent / undefined; } catch (error) { - return "Caught an error: " + error; + return "And the error is ... " + error; } - })()); + }).call(this)); })(); \ No newline at end of file diff --git a/documentation/js/long_arrow.js b/documentation/js/fat_arrow.js similarity index 100% rename from documentation/js/long_arrow.js rename to documentation/js/fat_arrow.js diff --git a/documentation/js/object_comprehensions.js b/documentation/js/object_comprehensions.js index 9c7d3783b9..ddc81f0526 100644 --- a/documentation/js/object_comprehensions.js +++ b/documentation/js/object_comprehensions.js @@ -15,5 +15,5 @@ } } return __a; - })(); + }).call(this); })(); \ No newline at end of file diff --git a/documentation/js/overview.js b/documentation/js/overview.js index 2098e3a30f..97b0f43589 100644 --- a/documentation/js/overview.js +++ b/documentation/js/overview.js @@ -39,5 +39,5 @@ __a.push(math.cube(num)); } return __a; - })(); + }).call(this); })(); \ No newline at end of file diff --git a/documentation/js/range_comprehensions.js b/documentation/js/range_comprehensions.js index 9272dcff38..a67917f4bb 100644 --- a/documentation/js/range_comprehensions.js +++ b/documentation/js/range_comprehensions.js @@ -6,7 +6,7 @@ __a.push(num); } return __a; - })(); + }).call(this); egg_delivery = function egg_delivery() { var __f, __g, __h, __i, __j, dozen_eggs, i; __f = []; __i = 0; __j = eggs.length; @@ -14,7 +14,7 @@ __f.push((function() { dozen_eggs = eggs.slice(i, i + 12); return deliver(new egg_carton(dozen)); - })()); + }).call(this)); } return __f; }; diff --git a/documentation/js/soaks.js b/documentation/js/soaks.js new file mode 100644 index 0000000000..efacb69265 --- /dev/null +++ b/documentation/js/soaks.js @@ -0,0 +1,4 @@ +(function(){ + var __a; + ((__a = lottery.draw_winner()) == undefined ? undefined : __a.address == undefined ? undefined : __a.address.zipcode); +})(); \ No newline at end of file diff --git a/documentation/js/splats.js b/documentation/js/splats.js index 4fb2085bca..052437fe47 100644 --- a/documentation/js/splats.js +++ b/documentation/js/splats.js @@ -1,7 +1,7 @@ (function(){ - var contenders, gold, medalists, silver, the_field; + var award_medals, contenders, gold, silver, the_field; gold = (silver = (the_field = "unknown")); - medalists = function medalists(first, second) { + award_medals = function award_medals(first, second) { var rest; rest = Array.prototype.slice.call(arguments, 2); gold = first; @@ -9,7 +9,7 @@ return the_field = rest; }; contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"]; - medalists.apply(this, contenders); + award_medals.apply(this, contenders); alert("Gold: " + gold); alert("Silver: " + silver); alert("The Field: " + the_field); diff --git a/documentation/js/while.js b/documentation/js/while.js index 0ac87e11a4..ee7f0b06bb 100644 --- a/documentation/js/while.js +++ b/documentation/js/while.js @@ -1,5 +1,6 @@ (function(){ var __a, lyrics, num; + // Econ 101 if (this.studying_economics) { while (supply > demand) { buy(); @@ -8,6 +9,7 @@ sell(); } } + // Nursery Rhyme num = 6; lyrics = (function() { __a = []; @@ -16,5 +18,5 @@ One fell out and bumped his head."); } return __a; - })(); + }).call(this); })(); \ No newline at end of file diff --git a/documentation/underscore.html b/documentation/underscore.html index 5ce7f0cc61..357a94c0a7 100644 --- a/documentation/underscore.html +++ b/documentation/underscore.html @@ -19,7 +19,7 @@

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

    +index: (list, target) -> [low, high]: [0, list.length] while low < high mid: (low + high) >> 1 diff --git a/examples/beautiful_code/quicksort_runtime.coffee b/examples/beautiful_code/quicksort_runtime.coffee index bbba050443..affd775a5e 100644 --- a/examples/beautiful_code/quicksort_runtime.coffee +++ b/examples/beautiful_code/quicksort_runtime.coffee @@ -1,7 +1,7 @@ # Beautiful Code, Chapter 3. # Produces the expected runtime of Quicksort, for every integer from 1 to N. -runtime: N => +runtime: (N) -> [sum, t]: [0, 0] for n in [1..N] sum += 2 * t diff --git a/examples/beautiful_code/regular_expression_matcher.coffee b/examples/beautiful_code/regular_expression_matcher.coffee index da6bd6962c..4ef8237e11 100644 --- a/examples/beautiful_code/regular_expression_matcher.coffee +++ b/examples/beautiful_code/regular_expression_matcher.coffee @@ -3,7 +3,7 @@ # '.', '^', '$', and '*'. # Search for the regexp anywhere in the text. -match: regexp, text => +match: (regexp, text) -> return match_here(regexp.slice(1), text) if regexp[0] is '^' while text return true if match_here(regexp, text) @@ -11,7 +11,7 @@ match: regexp, text => false # Search for the regexp at the beginning of the text. -match_here: regexp, text => +match_here: (regexp, text) -> [cur, next]: [regexp[0], regexp[1]] if regexp.length is 0 then return true if next is '*' then return match_star(cur, regexp.slice(2), text) @@ -20,7 +20,7 @@ match_here: regexp, text => false # Search for a kleene star match at the beginning of the text. -match_star: c, regexp, text => +match_star: (c, regexp, text) -> while true return true if match_here(regexp, text) return false unless text and (text[0] is c or c is '.') diff --git a/examples/code.coffee b/examples/code.coffee index 4917d0feee..85b7516948 100644 --- a/examples/code.coffee +++ b/examples/code.coffee @@ -1,14 +1,14 @@ # Functions: -square: x => x * x +square: (x) -> x * x -sum: x, y => x + y +sum: (x, y) -> x + y -odd: x => x % 2 is 0 +odd: (x) -> x % 2 isnt 0 -even: x => x % 2 isnt 0 +even: (x) -> x % 2 is 0 -run_loop: => - fire_events(e => e.stopPropagation()) +run_loop: -> + fire_events((e) -> e.stopPropagation()) listen() wait() @@ -22,14 +22,14 @@ spaced_out_multiline_object: { three: new Idea() inner_obj: { - freedom: => _.freedom() + freedom: -> _.freedom() } } # Arrays: stooges: [{moe: 45}, {curly: 43}, {larry: 46}] -exponents: [(x => x), (x => x * x), (x => x * x * x)] +exponents: [(x) -> x, (x) -> x * x, (x) -> x * x * x] empty: [] @@ -54,7 +54,7 @@ decoration: medal_of_honor if war_hero go_to_sleep() unless coffee # Returning early: -race: => +race: -> run() walk() crawl() @@ -103,7 +103,7 @@ while true # Lexical scoping. v_1: 5 -change_a_and_set_b: => +change_a_and_set_b: -> v_1: 10 v_2: 15 v_2: 20 @@ -128,7 +128,7 @@ activity: switch day else go_to_work() # Semicolons can optionally be used instead of newlines. -wednesday: => eat_breakfast(); go_to_work(); eat_dinner() +wednesday: -> eat_breakfast(); go_to_work(); eat_dinner() # Array slice literals. zero_to_nine: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -140,19 +140,19 @@ sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad." # Inheritance and calling super. -Animal: => -Animal::move: meters => +Animal: -> +Animal::move: (meters) -> alert(this.name + " moved " + meters + "m.") -Snake: name => this.name: name +Snake: (name) -> this.name: name Snake extends Animal -Snake::move: => +Snake::move: -> alert('Slithering...') super(5) -Horse: name => this.name: name +Horse: (name) -> this.name: name Horse extends Animal -Horse::move: => +Horse::move: -> alert('Galloping...') super(45) diff --git a/examples/computer_science/README b/examples/computer_science/README new file mode 100644 index 0000000000..1046f9f9b5 --- /dev/null +++ b/examples/computer_science/README @@ -0,0 +1,4 @@ +Ported from Nicholas Zakas' collection of computer science fundamentals, written +in JavaScript. Originals available here: + +http://github.com/nzakas/computer-science-in-javascript diff --git a/examples/computer_science/binary_search.coffee b/examples/computer_science/binary_search.coffee new file mode 100644 index 0000000000..443eaaa0fe --- /dev/null +++ b/examples/computer_science/binary_search.coffee @@ -0,0 +1,25 @@ +# Uses a binary search algorithm to locate a value in the specified array. +binary_search: (items, value) -> + + start: 0 + stop: items.length - 1 + pivot: Math.floor((start + stop) / 2) + + while items[pivot] isnt value and start < stop + + # Adjust the search area. + stop: pivot - 1 if value < items[pivot] + start: pivot + 1 if value > items[pivot] + + # Recalculate the pivot. + pivot: Math.floor((stop + start) / 2) + + # Make sure we've found the correct value. + if items[pivot] is value then pivot else -1 + + +# Test the function. +print(2 is binary_search([10, 20, 30, 40, 50], 30)) +print(4 is binary_search([-97, 35, 67, 88, 1200], 1200)) +print(0 is binary_search([0, 45, 70], 0)) +print(-1 is binary_search([0, 45, 70], 10)) \ No newline at end of file diff --git a/examples/computer_science/bubble_sort.coffee b/examples/computer_science/bubble_sort.coffee new file mode 100644 index 0000000000..f671bedd98 --- /dev/null +++ b/examples/computer_science/bubble_sort.coffee @@ -0,0 +1,11 @@ +# A bubble sort implementation, sorting the given array in-place. +bubble_sort: (list) -> + for i in [0...list.length] + for j in [0...list.length - i] + [list[j], list[j+1]]: [list[j+1], list[j]] if list[j] > list[j+1] + list + + +# Test the function. +print(bubble_sort([3, 2, 1]).join(' ') is '1 2 3') +print(bubble_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9') \ No newline at end of file diff --git a/examples/computer_science/linked_list.coffee b/examples/computer_science/linked_list.coffee new file mode 100644 index 0000000000..6af3fddfd0 --- /dev/null +++ b/examples/computer_science/linked_list.coffee @@ -0,0 +1,106 @@ +# "Classic" linked list implementation that doesn't keep track of its size. +LinkedList: -> + this._head: null # Pointer to the first item in the list. + + +# Appends some data to the end of the list. This method traverses the existing +# list and places the value at the end in a new node. +LinkedList::add: (data) -> + + # Create a new node object to wrap the data. + node: {data: data, next: null} + + current: this._head ||= node + + if this._head isnt node + current: current.next while current.next + current.next: node + + this + + +# Retrieves the data at the given position in the list. +LinkedList::item: (index) -> + + # Check for out-of-bounds values. + return null if index < 0 + + current: this._head or null + i: -1 + + # Advance through the list. + current: current.next while current and index > (i += 1) + + # Return null if we've reached the end. + current and current.data + + +# Remove the item from the given location in the list. +LinkedList::remove: (index) -> + + # Check for out-of-bounds values. + return null if index < 0 + + current: this._head or null + i: -1 + + # Special case: removing the first item. + if index is 0 + this._head: current.next + else + + # Find the right location. + [previous, current]: [current, current.next] while index > (i += 1) + + # Skip over the item to remove. + previous.next: current.next + + # Return the value. + current and current.data + + +# Calculate the number of items in the list. +LinkedList::size: -> + current: this._head + count: 0 + + while current + count += 1 + current: current.next + + count + + +# Convert the list into an array. +LinkedList::toArray: -> + result: [] + current: this._head + + while current + result.push(current.data) + current: current.next + + result + + +# The string representation of the linked list. +LinkedList::toString: -> this.toArray().toString() + + +# Tests. +list: new LinkedList() + +list.add("Hi") +print(list.size() is 1) +print(list.item(0) is "Hi") +print(list.item(1) is null) + +list: new LinkedList() +list.add("zero").add("one").add("two") +print(list.size() is 3) +print(list.item(2) is "two") +print(list.remove(1) is "one") +print(list.item(0) is "zero") +print(list.item(1) is "two") +print(list.size() is 2) +print(list.item(-10) is null) diff --git a/examples/computer_science/luhn_algorithm.coffee b/examples/computer_science/luhn_algorithm.coffee new file mode 100644 index 0000000000..042b249d6c --- /dev/null +++ b/examples/computer_science/luhn_algorithm.coffee @@ -0,0 +1,36 @@ +# Use the Luhn algorithm to validate a numeric identifier, such as credit card +# numbers, national insurance numbers, etc. +# See: http://en.wikipedia.org/wiki/Luhn_algorithm + +is_valid_identifier: (identifier) -> + + sum: 0 + alt: false + + for i in [(identifier.length - 1)..0] + + # Get the next digit. + num: parseInt(identifier.charAt(i), 10) + + # If it's not a valid number, abort. + return false if isNaN(num) + + # If it's an alternate number... + if alt + num *= 2 + num: (num % 10) + 1 if num > 9 + + # Flip the alternate bit. + alt: !alt + + # Add to the rest of the sum. + sum += num + + # Determine if it's valid. + sum % 10 is 0 + + +# Tests. +print(is_valid_identifier("49927398716") is true) +print(is_valid_identifier("4408041234567893") is true) +print(is_valid_identifier("4408041234567890") is false) diff --git a/examples/computer_science/merge_sort.coffee b/examples/computer_science/merge_sort.coffee new file mode 100644 index 0000000000..fb3f8ce8fc --- /dev/null +++ b/examples/computer_science/merge_sort.coffee @@ -0,0 +1,19 @@ +# Sorts an array in ascending natural order using merge sort. +merge_sort: (list) -> + + return list if list.length is 1 + + result: [] + pivot: Math.floor(list.length / 2) + left: merge_sort(list.slice(0, pivot)) + right: merge_sort(list.slice(pivot)) + + while left.length and right.length + result.push(if left[0] < right[0] then left.shift() else right.shift()) + + result.concat(left).concat(right) + + +# Test the function. +print(merge_sort([3, 2, 1]).join(' ') is '1 2 3') +print(merge_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9') \ No newline at end of file diff --git a/examples/computer_science/selection_sort.coffee b/examples/computer_science/selection_sort.coffee new file mode 100644 index 0000000000..f4b970a14a --- /dev/null +++ b/examples/computer_science/selection_sort.coffee @@ -0,0 +1,23 @@ +# An in-place selection sort. +selection_sort: (list) -> + len: list.length + + # For each item in the list. + for i in [0...len] + + # Set the minimum to this position. + min: i + + # Check the rest of the array to see if anything is smaller. + (min: j if list[j] < list[min]) for j in [i+1...len] + + # Swap if a smaller item has been found. + [list[i], list[min]]: [list[min], list[i]] if i isnt min + + # The list is now sorted. + list + + +# Test the function. +print(selection_sort([3, 2, 1]).join(' ') is '1 2 3') +print(selection_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9') \ No newline at end of file diff --git a/examples/documents.coffee b/examples/documents.coffee deleted file mode 100644 index 31d38d8ed4..0000000000 --- a/examples/documents.coffee +++ /dev/null @@ -1,72 +0,0 @@ -# Document Model -dc.model.Document: dc.Model.extend({ - - constructor: attributes => this.base(attributes) - - # For display, show either the highlighted search results, or the summary, - # if no highlights are available. - # The import process will take care of this in the future, but the inline - # version of the summary has all runs of whitespace squeezed out. - displaySummary: => - text: this.get('highlight') or this.get('summary') or '' - text and text.replace(/\s+/g, ' ') - - # Return a list of the document's metadata. Think about caching this on the - # document by binding to Metadata, instead of on-the-fly. - metadata: => - docId: this.id - _.select(Metadata.models(), (meta => - _.any(meta.get('instances'), instance => - instance.document_id is docId))) - - bookmark: pageNumber => - bookmark: new dc.model.Bookmark({title: this.get('title'), page_number: pageNumber, document_id: this.id}) - Bookmarks.create(bookmark) - - # Inspect. - toString: => 'Document ' + this.id + ' "' + this.get('title') + '"' - -}) - -# Document Set -dc.model.DocumentSet: dc.model.RESTfulSet.extend({ - - resource: 'documents' - - SELECTION_CHANGED: 'documents:selection_changed' - - constructor: options => - this.base(options) - _.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText') - - selected: => _.select(this.models(), m => m.get('selected')) - - selectedIds: => _.pluck(this.selected(), 'id') - - countSelected: => this.selected().length - - downloadSelectedViewers: => - dc.app.download('/download/' + this.selectedIds().join('/') + '/document_viewer.zip') - - downloadSelectedPDF: => - if this.countSelected() <= 1 then return window.open(this.selected()[0].get('pdf_url')) - dc.app.download('/download/' + this.selectedIds().join('/') + '/document_pdfs.zip') - - downloadSelectedFullText: => - if this.countSelected() <= 1 then return window.open(this.selected()[0].get('full_text_url')) - dc.app.download('/download/' + this.selectedIds().join('/') + '/document_text.zip') - - # We override "_onModelEvent" to fire selection changed events when documents - # change their selected state. - _onModelEvent: e, model => - this.base(e, model) - fire: e is dc.Model.CHANGED and model.hasChanged('selected') - if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this)) - -}) - -# The main set of Documents, used by the search tab. -window.Documents: new dc.model.DocumentSet() - -# The set of documents that is used to look at a particular label. -dc.app.LabeledDocuments: new dc.model.DocumentSet() diff --git a/examples/poignant.coffee b/examples/poignant.coffee index 9ed24328c8..0754284a75 100644 --- a/examples/poignant.coffee +++ b/examples/poignant.coffee @@ -2,7 +2,7 @@ # ['toast', 'cheese', 'wine'].each { |food| print food.capitalize } -['toast', 'wine', 'cheese'].each(food => print(food.capitalize())) +['toast', 'wine', 'cheese'].each (food) -> print(food.capitalize()) @@ -14,10 +14,43 @@ # end LotteryTicket: { - get_picks: => this.picks - set_picks: nums => this.picks: nums - get_purchase: => this.purchase - set_purchase: amount => this.purchase: amount + get_picks: -> this.picks + set_picks: (nums) -> this.picks: nums + get_purchase: -> this.purchase + set_purchase: (amount) -> this.purchase: amount +} + + + +# class << LotteryDraw +# def play +# result = LotteryTicket.new_random +# winners = {} +# @@tickets.each do |buyer, ticket_list| +# ticket_list.each do |ticket| +# score = ticket.score( result ) +# next if score.zero? +# winners[buyer] ||= [] +# winners[buyer] << [ ticket, score ] +# end +# end +# @@tickets.clear +# winners +# end +# end + +LotteryDraw: { + play: -> + result: LotteryTicket.new_random() + winners: {} + this.tickets.each (buyer, ticket_list) -> + ticket_list.each (ticket) -> + score: ticket.score(result) + return if score is 0 + winners[buyer] ||= [] + winners[buyer].push([ticket, score]) + this.tickets: {} + winners } @@ -32,8 +65,8 @@ LotteryTicket: { # end WishScanner: { - scan_for_a_wish: => - wish: this.read().detect(thought => thought.index('wish: ') is 0) + scan_for_a_wish: -> + wish: this.read().detect((thought) -> thought.index('wish: ') is 0) wish.replace('wish: ', '') } @@ -78,7 +111,7 @@ WishScanner: { Creature : { # This method applies a hit taken during a fight. - hit: damage => + hit: (damage) -> p_up: Math.rand(this.charisma) if p_up % 9 is 7 this.life += p_up / 4 @@ -87,7 +120,7 @@ Creature : { if this.life <= 0 then puts("[" + this.name + " has died.]") # This method takes one turn in a fight. - fight: enemy, weapon => + fight: (enemy, weapon) -> if this.life <= 0 then return puts("[" + this.name + "is too dead to fight!]") # Attack the opponent. @@ -123,12 +156,12 @@ Creature : { # Get evil idea and swap in code words print("Enter your new idea: ") idea: gets() -code_words.each(real, code => idea.replace(real, code)) +code_words.each((real, code) -> idea.replace(real, code)) # Save the jibberish to a new file print("File encoded. Please enter a name for this idea: ") idea_name: gets().strip() -File.open("idea-" + idea_name + '.txt', 'w', file => file.write(idea)) +File.open("idea-" + idea_name + '.txt', 'w', (file) -> file.write(idea)) @@ -144,7 +177,7 @@ File.open("idea-" + idea_name + '.txt', 'w', file => file.write(idea)) # end # end -wipe_mutterings_from: sentence => +wipe_mutterings_from: (sentence) -> throw new Error("cannot wipe mutterings") unless sentence.indexOf while sentence.indexOf('(') >= 0 open: sentence.indexOf('(') - 1 diff --git a/examples/potion.coffee b/examples/potion.coffee index de8f72c591..c8c5ddf9a3 100644 --- a/examples/potion.coffee +++ b/examples/potion.coffee @@ -8,7 +8,7 @@ print("Odelay!") for i in [1..5] # add = (x, y): x + y. # add(2, 4) string print -add: x, y => x + y +add: (x, y) -> x + y print(add(2, 4)) @@ -31,7 +31,7 @@ print({language: 'Potion', pointless: true}['language']) # minus = (x, y): x - y. # minus (y=10, x=6) -minus: x, y => x - y +minus: (x, y) -> x - y minus(6, 10) @@ -53,8 +53,8 @@ for key, val of {dog: 'canine', cat: 'feline', fox: 'vulpine'} # Person print = (): # ('My name is ', /name, '.') join print. -Person: => -Person::print: => +Person: -> +Person::print: -> print('My name is ' + this.name + '.') @@ -71,9 +71,9 @@ print(p.name) # # Policeman ('Constable') print -Policeman: rank => this.rank: rank +Policeman: (rank) -> this.rank: rank Policeman extends Person -Policeman::print: => +Policeman::print: -> print('My name is ' + this.name + " and I'm a " + this.rank + '.') print(new Policeman('Constable')) @@ -115,13 +115,13 @@ table: { # String length = (): 10. # this foul business... -String::length: => 10 +String::length: -> 10 # block = : # 'potion' print. -block: => +block: -> print('potion') @@ -178,7 +178,7 @@ if (3).gender? # HomePage get = (url): # session = url query ? at ('session'). -HomePage::get: url => +HomePage::get: (url) -> session: url.query.session if url.query? @@ -187,7 +187,7 @@ HomePage::get: url => # b /left = BTree () # b /right = BTree () -BTree: => +BTree: -> b: new BTree() b.left: new BTree() b.right: new BTree() @@ -199,7 +199,7 @@ b.right: new BTree() # if (b ? /left): # 'left path found!' print. -BTree: => +BTree: -> b: new BTree() print('left path found!') if b.left? diff --git a/examples/syntax_errors.coffee b/examples/syntax_errors.coffee deleted file mode 100644 index aa72cd71ee..0000000000 --- a/examples/syntax_errors.coffee +++ /dev/null @@ -1,20 +0,0 @@ -# Identifiers run together: -# a b c - -# Trailing comma in array: -# array: [1, 2, 3, 4, 5,] - -# Unterminated object literal: -# obj: { one: 1, two: 2 - -# Numbers run together: -# 101 202 - -# Strings run together: -# str: "broken" "words" - -# Forgot to terminate a function: -# obj: { -# first: a => a[0]. -# last: a => a[a.length-1] -# } \ No newline at end of file diff --git a/examples/underscore.coffee b/examples/underscore.coffee index edc3cb9a03..a34a1ce869 100644 --- a/examples/underscore.coffee +++ b/examples/underscore.coffee @@ -1,6 +1,6 @@ # Underscore.coffee - # (c) 2009 Jeremy Ashkenas, DocumentCloud Inc. + # (c) 2010 Jeremy Ashkenas, DocumentCloud Inc. # Underscore is freely distributable under the terms of the MIT license. # Portions of Underscore are inspired by or borrowed from Prototype.js, # Oliver Steele's Functional, and John Resig's Micro-Templating. @@ -21,7 +21,7 @@ # If Underscore is called as a function, it returns a wrapped object that # can be used OO-style. This wrapper holds altered versions of all the # underscore functions. Wrapped objects may be chained. - wrapper: obj => + wrapper: (obj) -> this._wrapped: obj this @@ -31,7 +31,7 @@ # Create a safe reference to the Underscore object forreference below. - _: root._: obj => new wrapper(obj) + _: root._: (obj) -> new wrapper(obj) # Export the Underscore object for CommonJS. @@ -47,14 +47,14 @@ # Current version. - _.VERSION: '0.5.5' + _.VERSION: '0.5.7' # ------------------------ Collection Functions: --------------------------- # The cornerstone, an each implementation. # Handles objects implementing forEach, arrays, and raw objects. - _.each: obj, iterator, context => + _.each: (obj, iterator, context) -> index: 0 try return obj.forEach(iterator, context) if obj.forEach @@ -68,36 +68,36 @@ # Return the results of applying the iterator to each element. Use JavaScript # 1.6's version of map, if possible. - _.map: obj, iterator, context => + _.map: (obj, iterator, context) -> return obj.map(iterator, context) if (obj and _.isFunction(obj.map)) results: [] - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> results.push(iterator.call(context, value, index, list)) results # Reduce builds up a single result from a list of values. Also known as # inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible. - _.reduce: obj, memo, iterator, context => + _.reduce: (obj, memo, iterator, context) -> return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce)) - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> memo: iterator.call(context, memo, value, index, list) memo # The right-associative version of reduce, also known as foldr. Uses # JavaScript 1.8's version of reduceRight, if available. - _.reduceRight: obj, memo, iterator, context => + _.reduceRight: (obj, memo, iterator, context) -> return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight)) - _.each(_.clone(_.toArray(obj)).reverse()) value, index => + _.each _.clone(_.toArray(obj)).reverse(), (value, index) -> memo: iterator.call(context, memo, value, index, obj) memo # Return the first value which passes a truth test. - _.detect: obj, iterator, context => + _.detect: (obj, iterator, context) -> result: null - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> if iterator.call(context, value, index, list) result: value _.breakLoop() @@ -106,47 +106,47 @@ # Return all the elements that pass a truth test. Use JavaScript 1.6's # filter(), if it exists. - _.select: obj, iterator, context => + _.select: (obj, iterator, context) -> if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context) results: [] - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> results.push(value) if iterator.call(context, value, index, list) results # Return all the elements for which a truth test fails. - _.reject: obj, iterator, context => + _.reject: (obj, iterator, context) -> results: [] - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> results.push(value) if not iterator.call(context, value, index, list) results # Determine whether all of the elements match a truth test. Delegate to # JavaScript 1.6's every(), if it is present. - _.all: obj, iterator, context => + _.all: (obj, iterator, context) -> iterator ||= _.identity return obj.every(iterator, context) if obj and _.isFunction(obj.every) result: true - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> _.breakLoop() unless (result: result and iterator.call(context, value, index, list)) result # Determine if at least one element in the object matches a truth test. Use # JavaScript 1.6's some(), if it exists. - _.any: obj, iterator, context => + _.any: (obj, iterator, context) -> iterator ||= _.identity return obj.some(iterator, context) if obj and _.isFunction(obj.some) result: false - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> _.breakLoop() if (result: iterator.call(context, value, index, list)) result # Determine if a given value is included in the array or object, # based on '==='. - _.include: obj, target => + _.include: (obj, target) -> return _.indexOf(obj, target) isnt -1 if _.isArray(obj) for key, val of obj return true if val is target @@ -154,49 +154,49 @@ # Invoke a method with arguments on every item in a collection. - _.invoke: obj, method => + _.invoke: (obj, method) -> args: _.rest(arguments, 2) (if method then val[method] else val).apply(val, args) for val in obj # Convenience version of a common use case of map: fetching a property. - _.pluck: obj, key => - _.map(obj, (val => val[key])) + _.pluck: (obj, key) -> + _.map(obj, ((val) -> val[key])) # Return the maximum item or (item-based computation). - _.max: obj, iterator, context => + _.max: (obj, iterator, context) -> return Math.max.apply(Math, obj) if not iterator and _.isArray(obj) result: {computed: -Infinity} - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> computed: if iterator then iterator.call(context, value, index, list) else value computed >= result.computed and (result: {value: value, computed: computed}) result.value # Return the minimum element (or element-based computation). - _.min: obj, iterator, context => + _.min: (obj, iterator, context) -> return Math.min.apply(Math, obj) if not iterator and _.isArray(obj) result: {computed: Infinity} - _.each(obj) value, index, list => + _.each obj, (value, index, list) -> computed: if iterator then iterator.call(context, value, index, list) else value computed < result.computed and (result: {value: value, computed: computed}) result.value # Sort the object's values by a criteria produced by an iterator. - _.sortBy: obj, iterator, context => - _.pluck(((_.map(obj) value, index, list => + _.sortBy: (obj, iterator, context) -> + _.pluck(((_.map obj, (value, index, list) -> {value: value, criteria: iterator.call(context, value, index, list)} - ).sort() left, right => + ).sort((left, right) -> a: left.criteria; b: right.criteria if a < b then -1 else if a > b then 1 else 0 - ), 'value') + )), 'value') # Use a comparator function to figure out at what index an object should # be inserted so as to maintain order. Uses binary search. - _.sortedIndex: array, obj, iterator => + _.sortedIndex: (array, obj, iterator) -> iterator ||= _.identity low: 0; high: array.length while low < high @@ -206,7 +206,7 @@ # Convert anything iterable into a real, live array. - _.toArray: iterable => + _.toArray: (iterable) -> return [] if (!iterable) return iterable.toArray() if (iterable.toArray) return iterable if (_.isArray(iterable)) @@ -215,7 +215,7 @@ # Return the number of elements in an object. - _.size: obj => _.toArray(obj).length + _.size: (obj) -> _.toArray(obj).length # -------------------------- Array Functions: ------------------------------ @@ -223,7 +223,7 @@ # Get the first element of an array. Passing "n" will return the first N # values in the array. Aliased as "head". The "guard" check allows it to work # with _.map. - _.first: array, n, guard => + _.first: (array, n, guard) -> if n and not guard then slice.call(array, 0, n) else array[0] @@ -231,35 +231,35 @@ # Especially useful on the arguments object. Passing an "index" will return # the rest of the values in the array from that index onward. The "guard" # check allows it to work with _.map. - _.rest: array, index, guard => + _.rest: (array, index, guard) -> slice.call(array, if _.isUndefined(index) or guard then 1 else index) # Get the last element of an array. - _.last: array => array[array.length - 1] + _.last: (array) -> array[array.length - 1] # Trim out all falsy values from an array. - _.compact: array => array[i] for i in [0...array.length] when array[i] + _.compact: (array) -> array[i] for i in [0...array.length] when array[i] # Return a completely flattened version of an array. - _.flatten: array => - _.reduce(array, []) memo, value => + _.flatten: (array) -> + _.reduce array, [], (memo, value) -> return memo.concat(_.flatten(value)) if _.isArray(value) memo.push(value) memo # Return a version of the array that does not contain the specified value(s). - _.without: array => + _.without: (array) -> values: _.rest(arguments) val for val in _.toArray(array) when not _.include(values, val) # Produce a duplicate-free version of the array. If the array has already # been sorted, you have the option of using a faster algorithm. - _.uniq: array, isSorted => + _.uniq: (array, isSorted) -> memo: [] for el, i in _.toArray(array) memo.push(el) if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el)) @@ -268,28 +268,27 @@ # Produce an array that contains every item shared between all the # passed-in arrays. - _.intersect: array => + _.intersect: (array) -> rest: _.rest(arguments) - _.select(_.uniq(array)) item => - _.all(rest) other => + _.select _.uniq(array), (item) -> + _.all rest, (other) -> _.indexOf(other, item) >= 0 # Zip together multiple lists into a single array -- elements that share # an index go together. - _.zip: => - args: _.toArray(arguments) - length: _.max(_.pluck(args, 'length')) + _.zip: -> + length: _.max(_.pluck(arguments, 'length')) results: new Array(length) for i in [0...length] - results[i]: _.pluck(args, String(i)) + results[i]: _.pluck(arguments, String(i)) results # If the browser doesn't supply us with indexOf (I'm looking at you, MSIE), # we need this function. Return the position of the first occurence of an # item in an array, or -1 if the item is not included in the array. - _.indexOf: array, item => + _.indexOf: (array, item) -> return array.indexOf(item) if array.indexOf i: 0; l: array.length while l - i @@ -299,7 +298,7 @@ # Provide JavaScript 1.6's lastIndexOf, delegating to the native function, # if possible. - _.lastIndexOf: array, item => + _.lastIndexOf: (array, item) -> return array.lastIndexOf(item) if array.lastIndexOf i: array.length while i @@ -310,8 +309,8 @@ # Generate an integer Array containing an arithmetic progression. A port of # the native Python range() function. See: # http://docs.python.org/library/functions.html#range - _.range: start, stop, step => - a: _.toArray(arguments) + _.range: (start, stop, step) -> + a: arguments solo: a.length <= 1 i: start: if solo then 0 else a[0]; stop: if solo then a[0] else a[1]; @@ -331,45 +330,45 @@ # Create a function bound to a given object (assigning 'this', and arguments, # optionally). Binding with arguments is also known as 'curry'. - _.bind: func, obj => + _.bind: (func, obj) -> args: _.rest(arguments, 2) - => func.apply(obj or root, args.concat(_.toArray(arguments))) + -> func.apply(obj or root, args.concat(arguments)) # Bind all of an object's methods to that object. Useful for ensuring that # all callbacks defined on an object belong to it. - _.bindAll: obj => + _.bindAll: (obj) -> funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(obj) - _.each(funcs, (f => obj[f]: _.bind(obj[f], obj))) + _.each(funcs, (f) -> obj[f]: _.bind(obj[f], obj)) obj # Delays a function for the given number of milliseconds, and then calls # it with the arguments supplied. - _.delay: func, wait => + _.delay: (func, wait) -> args: _.rest(arguments, 2) - setTimeout((=> func.apply(func, args)), wait) + setTimeout((-> func.apply(func, args)), wait) # Defers a function, scheduling it to run after the current call stack has # cleared. - _.defer: func => + _.defer: (func) -> _.delay.apply(_, [func, 1].concat(_.rest(arguments))) # Returns the first function passed as an argument to the second, # allowing you to adjust arguments, run code before and after, and # conditionally execute the original function. - _.wrap: func, wrapper => - => wrapper.apply(wrapper, [func].concat(_.toArray(arguments))) + _.wrap: (func, wrapper) -> + -> wrapper.apply(wrapper, [func].concat(arguments)) # Returns a function that is the composition of a list of functions, each # consuming the return value of the function that follows. - _.compose: => - funcs: _.toArray(arguments) - => - args: _.toArray(arguments) + _.compose: -> + funcs: arguments + -> + args: arguments for i in [(funcs.length - 1)..0] args: [funcs[i].apply(this, args)] args[0] @@ -378,43 +377,43 @@ # ------------------------- Object Functions: ---------------------------- # Retrieve the names of an object's properties. - _.keys: obj => + _.keys: (obj) -> return _.range(0, obj.length) if _.isArray(obj) key for key, val of obj # Retrieve the values of an object's properties. - _.values: obj => + _.values: (obj) -> _.map(obj, _.identity) # Return a sorted list of the function names available in Underscore. - _.functions: obj => - _.select(_.keys(obj), key => _.isFunction(obj[key])).sort() + _.functions: (obj) -> + _.select(_.keys(obj), (key) -> _.isFunction(obj[key])).sort() # Extend a given object with all of the properties in a source object. - _.extend: destination, source => + _.extend: (destination, source) -> for key, val of source destination[key]: val destination # Create a (shallow-cloned) duplicate of an object. - _.clone: obj => + _.clone: (obj) -> return obj.slice(0) if _.isArray(obj) _.extend({}, obj) # Invokes interceptor with the obj, and then returns obj. # The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. - _.tap: obj, interceptor => + _.tap: (obj, interceptor) -> interceptor(obj) obj # Perform a deep comparison to check if two objects are equal. - _.isEqual: a, b => + _.isEqual: (a, b) -> # Check object identity. return true if a is b # Different types? @@ -450,93 +449,104 @@ # Is a given array or object empty? - _.isEmpty: obj => _.keys(obj).length is 0 + _.isEmpty: (obj) -> _.keys(obj).length is 0 # Is a given value a DOM element? - _.isElement: obj => obj and obj.nodeType is 1 + _.isElement: (obj) -> obj and obj.nodeType is 1 # Is a given value an array? - _.isArray: obj => !!(obj and obj.concat and obj.unshift) + _.isArray: (obj) -> !!(obj and obj.concat and obj.unshift) # Is a given variable an arguments object? - _.isArguments: obj => obj and _.isNumber(obj.length) and !_.isArray(obj) and !propertyIsEnumerable.call(obj, 'length') + _.isArguments: (obj) -> obj and _.isNumber(obj.length) and not obj.concat and + not obj.substr and not obj.apply and not propertyIsEnumerable.call(obj, 'length') # Is the given value a function? - _.isFunction: obj => !!(obj and obj.constructor and obj.call and obj.apply) + _.isFunction: (obj) -> !!(obj and obj.constructor and obj.call and obj.apply) # Is the given value a string? - _.isString: obj => !!(obj is '' or (obj and obj.charCodeAt and obj.substr)) + _.isString: (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr)) # Is a given value a number? - _.isNumber: obj => toString.call(obj) is '[object Number]' + _.isNumber: (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]' # Is a given value a Date? - _.isDate: obj => !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear) + _.isDate: (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear) # Is the given value a regular expression? - _.isRegExp: obj => !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false)) + _.isRegExp: (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false)) # Is the given value NaN -- this one is interesting. NaN != NaN, and # isNaN(undefined) == true, so we make sure it's a number first. - _.isNaN: obj => _.isNumber(obj) and window.isNaN(obj) + _.isNaN: (obj) -> _.isNumber(obj) and window.isNaN(obj) # Is a given value equal to null? - _.isNull: obj => obj is null + _.isNull: (obj) -> obj is null # Is a given variable undefined? - _.isUndefined: obj => typeof obj is 'undefined' + _.isUndefined: (obj) -> typeof obj is 'undefined' # -------------------------- Utility Functions: -------------------------- # Run Underscore.js in noConflict mode, returning the '_' variable to its # previous owner. Returns a reference to the Underscore object. - _.noConflict: => + _.noConflict: -> root._: previousUnderscore this # Keep the identity function around for default iterators. - _.identity: value => value + _.identity: (value) -> value # Break out of the middle of an iteration. - _.breakLoop: => throw breaker + _.breakLoop: -> throw breaker # Generate a unique integer id (unique within the entire client session). # Useful for temporary DOM ids. idCounter: 0 - _.uniqueId: prefix => + _.uniqueId: (prefix) -> (prefix or '') + idCounter++ + # By default, Underscore uses ERB-style template delimiters, change the + # following template settings to use alternative delimiters. + _.templateSettings: { + start: '<%' + end: '%>' + interpolate: /<%=(.+?)%>/g + } + + # JavaScript templating a-la ERB, pilfered from John Resig's # "Secrets of the JavaScript Ninja", page 83. - _.template: str, data => - `var fn = new Function('obj', + # Single-quotea fix from Rick Strahl's version. + _.template: (str, data) -> + c: _.templateSettings + fn: new Function 'obj', 'var p=[],print=function(){p.push.apply(p,arguments);};' + 'with(obj){p.push(\'' + - str. - replace(/[\r\t\n]/g, " "). - split("<%").join("\t"). - replace(/((^|%>)[^\t]*)'/g, "$1\r"). - replace(/\t=(.*?)%>/g, "',$1,'"). - split("\t").join("');"). - split("%>").join("p.push('"). - split("\r").join("\\'") + - "');}return p.join('');")` + str.replace(/[\r\t\n]/g, " ") + .replace(new RegExp("'(?=[^"+c.end[0]+"]*"+c.end+")","g"),"\t") + .split("'").join("\\'") + .split("\t").join("'") + .replace(c.interpolate, "',$1,'") + .split(c.start).join("');") + .split(c.end).join("p.push('") + + "');}return p.join('');" if data then fn(data) else fn @@ -556,39 +566,38 @@ # /*------------------------ Setup the OOP Wrapper: --------------------------*/ # Helper function to continue chaining intermediate results. - result: obj, chain => + result: (obj, chain) -> if chain then _(obj).chain() else obj # Add all of the Underscore functions to the wrapper object. - _.each(_.functions(_)) name => + _.each _.functions(_), (name) -> method: _[name] - wrapper.prototype[name]: => - args: _.toArray(arguments) - unshift.call(args, this._wrapped) - result(method.apply(_, args), this._chain) + wrapper.prototype[name]: -> + unshift.call(arguments, this._wrapped) + result(method.apply(_, arguments), this._chain) # Add all mutator Array functions to the wrapper. - _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift']) name => + _.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) -> method: Array.prototype[name] - wrapper.prototype[name]: => + wrapper.prototype[name]: -> method.apply(this._wrapped, arguments) result(this._wrapped, this._chain) # Add all accessor Array functions to the wrapper. - _.each(['concat', 'join', 'slice']) name => + _.each ['concat', 'join', 'slice'], (name) -> method: Array.prototype[name] - wrapper.prototype[name]: => + wrapper.prototype[name]: -> result(method.apply(this._wrapped, arguments), this._chain) # Start chaining a wrapped Underscore object. - wrapper::chain: => + wrapper::chain: -> this._chain: true this # Extracts the result from a wrapped and chained object. - wrapper::value: => this._wrapped + wrapper::value: -> this._wrapped diff --git a/lib/coffee_script/CoffeeScript.tmbundle/Preferences/CoffeeScript.tmPreferences b/extras/CoffeeScript.tmbundle/Preferences/CoffeeScript.tmPreferences similarity index 100% rename from lib/coffee_script/CoffeeScript.tmbundle/Preferences/CoffeeScript.tmPreferences rename to extras/CoffeeScript.tmbundle/Preferences/CoffeeScript.tmPreferences diff --git a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage b/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage similarity index 92% rename from lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage rename to extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage index f0daaede1e..49082c8a1b 100644 --- a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage +++ b/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage @@ -19,52 +19,31 @@ captures - 1 + 1 name - entity.name.function.coffee + variable.parameter.function.coffee 2 - - name - keyword.operator.coffee - - 3 name variable.parameter.function.coffee 4 - - name - storage.type.function.coffee - - - comment - match stuff like: funcName: => … - match - ([a-zA-Z0-9_?.$:*]*?)\s*(=\b|:\b)\s*([\w,\s]*?)\s*(=+>) - name - meta.function.coffee - - - captures - - 1 name variable.parameter.function.coffee - 2 + 5 name storage.type.function.coffee comment - match stuff like: a => … + match stuff like: a -> … match - ([a-zA-Z0-9_?., $*]*)\s*(=+>) + (\()([a-zA-Z0-9_?.$]*(,\s*[a-zA-Z0-9_?.$]+)*)(\))\s*((=|-)>) name meta.inline.function.coffee @@ -313,6 +292,12 @@ name keyword.other.coffee + + match + (=|-)> + name + storage.type.function.coffee + match !|%|&|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(instanceof|new|delete|typeof|and|or|is|isnt|not)\b diff --git a/lib/coffee_script/CoffeeScript.tmbundle/info.plist b/extras/CoffeeScript.tmbundle/info.plist similarity index 100% rename from lib/coffee_script/CoffeeScript.tmbundle/info.plist rename to extras/CoffeeScript.tmbundle/info.plist diff --git a/extras/EXTRAS b/extras/EXTRAS new file mode 100644 index 0000000000..d555e3fb76 --- /dev/null +++ b/extras/EXTRAS @@ -0,0 +1,20 @@ +This folder includes rough cuts of CoffeeScript syntax highlighters for +TextMate and Vim. Improvements to their lexing ability are always welcome. + +To install the TextMate bundle, run `bin/coffee --install-bundle`, or drop it +into "~/Library/Application Support/TextMate/Bundles". + +To install the Vim highlighter, copy "coffee.vim" into the "syntax" directory of +your vim72, and enable it in either of the following two ways: + + * Manually, by running `:set syntax=coffee` + + * Or automatically, by creating a "filetype.vim" file within "~/.vim", which + contains something along these lines: + + if exists("did_load_filetypes") + finish + end + augroup filetypedetect + au! BufRead,BufNewFile *.coffee setfiletype coffee + augroup END diff --git a/extras/coffee.vim b/extras/coffee.vim new file mode 100644 index 0000000000..5235d3cbe4 --- /dev/null +++ b/extras/coffee.vim @@ -0,0 +1,111 @@ +" Vim syntax file +" Language: CoffeeScript +" Maintainer: Jeff Olson +" URL: http://github.com/olsonjeffery +" Changes: (jro) initial port from javascript +" Last Change: 2006 Jun 19 +" Adaptation of javascript.vim syntax file (distro'd w/ vim72), +" maintained by Claudio Fleiner +" with updates from Scott Shattuck (ss) + +if !exists("main_syntax") + if version < 600 + syntax clear + elseif exists("b:current_syntax") + finish + endif + let main_syntax = 'coffee' +endif + +syn case ignore + +syn match coffeeLineComment "#.*" contains=@Spell,CoffeeCommentTodo +syn match coffeeSpecial "\\\d\d\d\|\\." +syn region coffeeStringD start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ contains=coffeeSpecial,@htmlPreproc +syn region coffeeStringS start=+'+ skip=+\\\\\|\\'+ end=+'\|$+ contains=coffeeSpecial,@htmlPreproc + +syn match coffeeSpecialCharacter "'\\.'" +syn match coffeeNumber "-\=\<\d\+L\=\>\|0[xX][0-9a-fA-F]\+\>" +syn region coffeeRegexpString start=+/[^/*]+me=e-1 skip=+\\\\\|\\/+ end=+/[gi]\{0,2\}\s*$+ end=+/[gi]\{0,2\}\s*[;.,)\]}]+me=e-1 contains=@htmlPreproc oneline + +syn match coffeePrototypeAccess "::" +syn match coffeeFunction "->" + +syn keyword coffeeExtends extends +syn keyword coffeeConditional if else switch then +syn keyword coffeeRepeat while for in of +syn keyword coffeeBranch break continue +syn keyword coffeeOperator delete instanceof typeof +syn keyword coffeeType Array Boolean Date Function Number Object String RegExp +syn keyword coffeeStatement return with +syn keyword coffeeBoolean true false +syn keyword coffeeNull null undefined +syn keyword coffeeIdentifier arguments this var +syn keyword coffeeLabel case default +syn keyword coffeeException try catch finally throw +syn keyword coffeeMessage alert confirm prompt status +syn keyword coffeeGlobal self window top parent +syn keyword coffeeMember document event location +syn keyword coffeeDeprecated escape unescape +syn keyword coffeeReserved abstract boolean byte char class const debugger double enum export final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile + +syn sync fromstart +syn sync maxlines=100 + +if main_syntax == "coffee" + syn sync ccomment coffeeComment +endif + +" Define the default highlighting. +" For version 5.7 and earlier: only when not done already +" For version 5.8 and later: only when an item doesn't have highlighting yet +if version >= 508 || !exists("did_coffee_syn_inits") + if version < 508 + let did_coffee_syn_inits = 1 + command -nargs=+ HiLink hi link + else + command -nargs=+ HiLink hi def link + endif + HiLink coffeePrototypeAccess Keyword + HiLink coffeeExtends Keyword + HiLink coffeeLineComment Comment + HiLink coffeeSpecial Special + HiLink coffeeStringS String + HiLink coffeeStringD String + HiLink coffeeCharacter Character + HiLink coffeeSpecialCharacter coffeeSpecial + HiLink coffeeNumber coffeeValue + HiLink coffeeConditional Conditional + HiLink coffeeRepeat Repeat + HiLink coffeeBranch Conditional + HiLink coffeeOperator Operator + HiLink coffeeType Type + HiLink coffeeStatement Statement + HiLink coffeeFunction Function + HiLink coffeeBraces Function + HiLink coffeeError Error + HiLink coffeeScrParenError coffeeError + HiLink coffeeNull Keyword + HiLink coffeeBoolean Boolean + HiLink coffeeRegexpString String + + HiLink coffeeIdentifier Identifier + HiLink coffeeLabel Label + HiLink coffeeException Exception + HiLink coffeeMessage Keyword + HiLink coffeeGlobal Keyword + HiLink coffeeMember Keyword + HiLink coffeeDeprecated Exception + HiLink coffeeReserved Keyword + HiLink coffeeDebug Debug + HiLink coffeeConstant Label + + delcommand HiLink +endif + +let b:current_syntax = "coffee" +if main_syntax == 'coffee' + unlet main_syntax +endif + +" vim: ts=8 diff --git a/index.html b/index.html index f0e579af5e..86ed85b874 100644 --- a/index.html +++ b/index.html @@ -37,7 +37,7 @@

    CoffeeScript

    Latest Version: - 0.2.6 + 0.3.0

    Table of Contents

    @@ -51,7 +51,6 @@

    Table of Contents

    Objects and Arrays
    Lexical Scoping and Variable Safety
    Conditionals, Ternaries, and Conditional Assignment
    - The Existential Operator
    Aliases
    Splats...
    Arguments are Arrays
    @@ -59,17 +58,16 @@

    Table of Contents

    Comprehensions (Arrays, Objects, and Ranges)
    Array Slicing and Splicing with Ranges
    Everything is an Expression
    + The Existential Operator
    Inheritance, and Calling Super from a Subclass
    - Blocks
    Pattern Matching
    - Function Binding
    + Function Binding
    Embedded JavaScript
    Switch/When/Else
    Try/Catch/Finally
    Chained Comparisons
    Multiline Strings and Heredocs
    Resources
    - Contributing
    Change Log

    @@ -85,7 +83,7 @@

    Mini Overview

    number: -42 if opposite_day # Functions: -square: x => x * x +square: (x) -> x * x # Arrays: list: [1, 2, 3, 4, 5] @@ -94,18 +92,18 @@

    Mini Overview

    math: { root: Math.sqrt square: square - cube: x => x * square(x) + cube: (x) -> x * square x } # Splats: -race: winner, runners... => - print(winner, runners) +race: (winner, runners...) -> + print winner, runners # Existence: -alert("I knew it!") if elvis? +alert "I knew it!" if elvis? # Array comprehensions: -cubed_list: math.cube(num) for num in list +cubed_list: math.cube num for num in list
    var __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
     // Assignment:
     number = 42;
    @@ -146,7 +144,7 @@ 

    Mini Overview

    __a.push(math.cube(num)); } return __a; -})(); +}).call(this);

    @@ -271,7 +269,7 @@

    Installation and Usage

    -e, --eval Compile and print a little snippet of CoffeeScript directly from the - command line (or from stdin). For example:
    coffee -e "square: x => x * x" + command line (or from stdin). For example:
    coffee -e "square: (x) -> x * x" @@ -285,7 +283,7 @@

    Installation and Usage

    -v, --verbose As the JavaScript is being generated, print out every step of code - generation, including lexical scope and the node in the + generation, including lexical scope and the nodes in the AST. @@ -345,22 +343,24 @@

    Language Reference

    use indentation.

    +

    + You don't need to use parentheses to invoke a function, if you're passing + arguments:
    print "coffee" +

    +

    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. + as long as CoffeeScript can determine that the line hasn't finished yet.

    Functions and Invocation Functions are defined by a list of parameters, an arrow, and the - function body. The empty function looks like this: =>. All - functions in CoffeeScript are named by default, for the benefit of debug messages. - If you'd like to create an anonymous function, just wrap it in parentheses. + function body. The empty function looks like this: ->. All + functions in CoffeeScript are named by default, for easier debugging.

    -
    square: x => x * x
    -cube:   x => square(x) * x
    +    
    square: (x) -> x * x
    +cube:   (x) -> square(x) * x
     
    var cube, square;
     square = function square(x) {
       return x * x;
    @@ -376,6 +376,10 @@ 

    Language Reference

    return square(x) * x; }; ;alert(cube(5));'>run: cube(5)
    +

    + If you'd like to create an anonymous function, just wrap it in parentheses: + ((x) -> x * x) +

    Assignment @@ -393,7 +397,7 @@

    Language Reference

    difficulty = 0.5; ;alert(greeting);'>run: greeting

    - Declarations of new variables are pushed up to the top of the nearest + Declaration of new variables are pushed up to the top of the nearest lexical scope, so that assignment may always be performed within expressions.

    @@ -402,7 +406,7 @@

    Language Reference

    Object and Array literals look very similar to their JavaScript cousins. When you spread out each assignment on a separate line, the commas are optional. In this way, assigning object properties looks the same as - assigning local variables, and can be moved around freely. You can mix + assigning local variables, and can be moved around freely. Feel free to mix and match the two styles.

    song: ["do", "re", "mi", "fa", "so"]
    @@ -443,7 +447,7 @@ 

    Language Reference

    var yourself.

    num: 1
    -change_numbers: =>
    +change_numbers: ->
       new_num: -1
       num: 10
     new_num: change_numbers()
    @@ -477,9 +481,14 @@ 

    Language Reference

    CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult - to pollute the global namespace by accident. If you'd like to create - global variables, attach them as properties on window, - or on the exports object in CommonJS. + to pollute the global namespace by accident. +

    +

    + If you'd like to create top-level variables for other scripts to use, + attach them as properties on window, or on the exports + object in CommonJS. The existential operator (below), gives you a + reliable way to figure out where to add them, if you're targeting both + CommonJS and the browser: root: exports ? this

    @@ -520,38 +529,6 @@

    Language Reference

    truthy variables.

    -

    - The Existential Operator - It's a little difficult to check for the existence of a variable in - JavaScript. if (variable) ... comes close, but fails for zero, - the empty string, and false. The existential operator ? returns true unless - a variable is null or undefined, which makes it analogous - to Ruby's nil? -

    -

    - It can also be used for safer conditional assignment than ||= - provides, for cases where you may be handling numbers or strings. -

    -
    solipsism: true if mind? and not world?
    -
    -speed ?= 140
    -
    -
    -
    -
    -
    -
    var solipsism, speed;
    -if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
    -  solipsism = true;
    -}
    -speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
    -

    -

    Aliases Because the == operator frequently causes undesirable coercion, @@ -605,11 +582,11 @@

    Language Reference

    The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, - making variable arguments a little bit more palatable. + making variable numbers of arguments a little bit more palatable.

    gold: silver: the_field: "unknown"
     
    -medalists: first, second, rest... =>
    +award_medals: (first, second, rest...) ->
       gold:       first
       silver:     second
       the_field:  rest
    @@ -627,14 +604,14 @@ 

    Language Reference

    "Usain Bolt" ] -medalists(contenders...) +award_medals contenders... -alert("Gold: " + gold) -alert("Silver: " + silver) -alert("The Field: " + the_field) -
    var contenders, gold, medalists, silver, the_field;
    +alert "Gold: " + gold
    +alert "Silver: " + silver
    +alert "The Field: " + the_field
    +
    var award_medals, contenders, gold, silver, the_field;
     gold = (silver = (the_field = "unknown"));
    -medalists = function medalists(first, second) {
    +award_medals = function award_medals(first, second) {
       var rest;
       rest = Array.prototype.slice.call(arguments, 2);
       gold = first;
    @@ -642,13 +619,13 @@ 

    Language Reference

    return the_field = rest; }; contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"]; -medalists.apply(this, contenders); +award_medals.apply(this, contenders); alert("Gold: " + gold); alert("Silver: " + silver); alert("The Field: " + the_field); -

    Other JavaScript loops, such as for loops and do-while loops @@ -761,7 +744,7 @@

    Language Reference

    # Naive collision detection. for roid in asteroids for roid2 in asteroids when roid isnt roid2 - roid.explode() if roid.overlaps(roid2) + roid.explode() if roid.overlaps roid2
    var __a, __b, __c, __d, __e, __f, __g, food, lunch, roid, roid2;
     // Eat lunch.
     lunch = (function() {
    @@ -771,7 +754,7 @@ 

    Language Reference

    __a.push(eat(food)); } return __a; -})(); +}).call(this); // Naive collision detection. __d = asteroids; for (__e = 0; __e < __d.length; __e++) { @@ -795,10 +778,10 @@

    Language Reference

    countdown: num for num in [10..1]
     
    -egg_delivery: =>
    +egg_delivery: ->
       for i in [0...eggs.length] by 12
         dozen_eggs: eggs[i...i+12]
    -    deliver(new egg_carton(dozen))
    +    deliver new egg_carton(dozen)
     
    var __a, __b, __c, __d, __e, countdown, egg_delivery, num;
     countdown = (function() {
       __a = []; __d = 10; __e = 1;
    @@ -806,7 +789,7 @@ 

    Language Reference

    __a.push(num); } return __a; -})(); +}).call(this); egg_delivery = function egg_delivery() { var __f, __g, __h, __i, __j, dozen_eggs, i; __f = []; __i = 0; __j = eggs.length; @@ -814,7 +797,7 @@

    Language Reference

    __f.push((function() { dozen_eggs = eggs.slice(i, i + 12); return deliver(new egg_carton(dozen)); - })()); + }).call(this)); } return __f; }; @@ -825,7 +808,7 @@

    Language Reference

    __a.push(num); } return __a; -})(); +}).call(this); egg_delivery = function egg_delivery() { var __f, __g, __h, __i, __j, dozen_eggs, i; __f = []; __i = 0; __j = eggs.length; @@ -833,7 +816,7 @@

    Language Reference

    __f.push((function() { dozen_eggs = eggs.slice(i, i + 12); return deliver(new egg_carton(dozen)); - })()); + }).call(this)); } return __f; }; @@ -863,7 +846,7 @@

    Language Reference

    } } return __a; -})(); +}).call(this);

    @@ -933,7 +916,7 @@

    Language Reference

    pushed down into each possible branch of execution, in the function below.

    -
    grade: student =>
    +    
    grade: (student) ->
       if student.excellent_work
         "A+"
       else if student.okay_stuff
    @@ -1000,7 +983,7 @@ 

    Language Reference

    } } return __a; -})()).slice(0, 10); +}).call(this)).slice(0, 10);

    As well as silly things, like passing a try/catch statement directly @@ -1022,29 +1005,79 @@

    Language Reference

    try nonexistent / undefined catch error - "Caught an error: " + error + "And the error is ... " + error )
    alert((function() {
       try {
         return nonexistent / undefined;
       } catch (error) {
    -    return "Caught an error: " + error;
    +    return "And the error is ... " + error;
       }
    -})());
    +}).call(this));
     

    There are a handful of statements in JavaScript that can't be meaningfully - converted into expressions: break, continue, - and return. If you make use of them within a block of code, + converted into expressions, namely break, continue, + and return. If you make use of them within a block of code, CoffeeScript won't try to perform the conversion.

    + +

    + The Existential Operator + It's a little difficult to check for the existence of a variable in + JavaScript. if (variable) ... comes close, but fails for zero, + the empty string, and false. CoffeeScript's existential operator ? returns true unless + a variable is null or undefined, which makes it analogous + to Ruby's nil? +

    +

    + It can also be used for safer conditional assignment than ||= + provides, for cases where you may be handling numbers or strings. +

    +
    solipsism: true if mind? and not world?
    +
    +speed ?= 140
    +
    +
    +
    +
    +
    +
    var solipsism, speed;
    +if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
    +  solipsism = true;
    +}
    +speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
    +

    +

    + The accessor variant of the existential operator ?. can be used to soak + up null references in a chain of properties. Use it instead + of the dot accessor . in cases where the base value may be null + or undefined. If all of the properties exist then you'll get the expected + result, if the chain is broken, undefined is returned instead of + the TypeError that would be raised otherwise. +

    +
    lottery.draw_winner()?.address?.zipcode
    +
    var __a;
    +((__a = lottery.draw_winner()) == undefined ? undefined : __a.address == undefined ? undefined : __a.address.zipcode);
    +

    +

    + Soaking up nulls is similar to Ruby's + andand gem, and to the + safe navigation operator + in Groovy. +

    Inheritance, and Calling Super from a Subclass @@ -1066,24 +1099,24 @@

    Language Reference

    object's prototype, and converts super() into a call against the immediate ancestor's method of the same name.

    -
    Animal: =>
    -Animal::move: meters =>
    -  alert(this.name + " moved " + meters + "m.")
    +    
    Animal: ->
    +Animal::move: (meters) ->
    +  alert this.name + " moved " + meters + "m."
     
    -Snake: name => this.name: name
    +Snake: (name) -> this.name: name
     Snake extends Animal
    -Snake::move: =>
    -  alert("Slithering...")
    -  super(5)
    +Snake::move: ->
    +  alert "Slithering..."
    +  super 5
     
    -Horse: name => this.name: name
    +Horse: (name) -> this.name: name
     Horse extends Animal
    -Horse::move: =>
    -  alert("Galloping...")
    -  super(45)
    +Horse::move: ->
    +  alert "Galloping..."
    +  super 45
     
    -sam: new Snake("Sammy the Python")
    -tom: new Horse("Tommy the Palomino")
    +sam: new Snake "Sammy the Python"
    +tom: new Horse "Tommy the Palomino"
     
     sam.move()
     tom.move()
    @@ -1167,30 +1200,6 @@ 

    Language Reference

    tom.move(); ;'>run
    -

    - Blocks - Many common looping functions (in Prototype, jQuery, and Underscore, - for example) take a single function as their final argument. To make - final functions easier to pass, CoffeeScript includes block syntax, - so you don't have to close the parentheses on the other side. -

    -
    $('table.list').each() table =>
    -  $('tr.account', table).each() row =>
    -    row.show()
    -    row.highlight()
    -
    $('table.list').each(function(table) {
    -  return $('tr.account', table).each(function(row) {
    -    row.show();
    -    return row.highlight();
    -  });
    -});
    -

    -

    - If you prefer not to use blocks, you'll need to add a pair of parentheses - to help distinguish the arguments from the definition of the function: - _.map(array, (num => num * 2)) -

    -

    Pattern Matching (Destructuring Assignment) To make extracting values from complex arrays and objects more convenient, @@ -1222,11 +1231,11 @@

    Language Reference

    But it's also helpful for dealing with functions that return multiple values.

    -
    weather_report: location =>
    +    
    weather_report: (location) ->
       # Make an Ajax request to fetch the weather...
       [location, 72, "Mostly Sunny"]
     
    -[city, temp, forecast]: weather_report("Berkeley, CA")
    +[city, temp, forecast]: weather_report "Berkeley, CA"
     
    var __a, city, forecast, temp, weather_report;
     weather_report = function weather_report(location) {
       // Make an Ajax request to fetch the weather...
    @@ -1295,21 +1304,21 @@ 

    Language Reference

    city = __c[1]; ;alert(poet + " — " + street);'>run: poet + " — " + street
    -

    +

    Function binding - The long arrow ==> can be used to both define a function, and to bind + The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions - to use with bind. Functions created with the long arrow are able to access + to use with bind. Functions created with the fat arrow are able to access properties of the this where they're defined.

    -
    Account: customer, cart =>
    +    
    Account: (customer, cart) ->
       this.customer: customer
       this.cart: cart
     
    -  $('.shopping_cart').bind('click') event ==>
    -    this.customer.purchase(this.cart)
    +  $('.shopping_cart').bind 'click', (event) =>
    +    this.customer.purchase this.cart
     
    var Account;
     Account = function Account(customer, cart) {
       var __a;
    @@ -1400,7 +1409,7 @@ 

    Language Reference

    all_hell_breaks_loose() cats_and_dogs_living_together() catch error - print(error) + print error finally clean_up()
    try {
    @@ -1466,11 +1475,11 @@ 

    Language Reference

    indentation level that begins the heredoc is maintained throughout, so you can keep it all aligned with the body of your code.

    -
    html: '''
    +    
    html: '''
           <strong>
             cup of coffeescript
           </strong>
    -      '''
    +      '''
     
    var html;
     html = "<strong>\n  cup of coffeescript\n</strong>";
     

    @@ -1490,6 +1499,12 @@

    Resources

  • Bugs, Feature Requests, and General Discussion
  • +
  • + CoffeePot
    + An implementation of CoffeeScript, written in CoffeeScript, by + Tim Caswell. Compiles just + a limited subset at this point. +
  • BistroCar
    A Rails plugin by @@ -1505,39 +1520,24 @@

    Resources

  • -

    Contributing

    +

    Change Log

    - Here's a wish list of things that would be wonderful to have contributed: + 0.3.0 + CoffeeScript 0.3 includes major syntax changes: +
    + The function symbol was changed to + ->, and the bound function symbol is now =>. +
    + Parameter lists in function definitions must now be wrapped in parentheses. +
    + Added property soaking, with the ?. operator. +
    + Made parentheses optional, when invoking functions with arguments. +
    + Removed the obsolete block literal syntax.

    -
      -
    • - - A CoffeeScript version of the compiler. - -
    • -
    • - Test cases for any syntax errors you encounter that you think CoffeeScript - should be able to compile properly. -
    • -
    • - A tutorial that introduces CoffeeScript from the ground up for folks - without knowledge of JavaScript. -
    • -
    • - Integration with Processing.js's JavaScript API (this would depend on - having a JavaScript version of the compiler). -
    • -
    • - A lot of the code generation in nodes.rb gets into messy - string manipulation. Techniques for cleaning this up across the board - would be appreciated. -
    • -
    - -

    Change Log

    -

    0.2.6 Added Python-style chained comparisons, the conditional existence diff --git a/lib/coffee-script.rb b/lib/coffee-script.rb index 399cb9a8a2..73189edd60 100644 --- a/lib/coffee-script.rb +++ b/lib/coffee-script.rb @@ -10,7 +10,7 @@ # Namespace for all CoffeeScript internal classes. module CoffeeScript - VERSION = '0.2.6' # Keep in sync with the gemspec. + VERSION = '0.3.0' # Keep in sync with the gemspec. # Compile a script (String or IO) to JavaScript. def self.compile(script, options={}) diff --git a/lib/coffee_script/command_line.rb b/lib/coffee_script/command_line.rb index 30ad1e11a0..2427169a1c 100644 --- a/lib/coffee_script/command_line.rb +++ b/lib/coffee_script/command_line.rb @@ -25,9 +25,11 @@ class CommandLine # Seconds to pause between checks for changed source files. WATCH_INTERVAL = 0.5 + # Path to the root of the CoffeeScript install. + ROOT = File.expand_path(File.dirname(__FILE__) + '/../..') + # Command to execute in Narwhal - PACKAGE = File.expand_path(File.dirname(__FILE__) + '/../..') - LAUNCHER = "narwhal -p #{PACKAGE} -e 'require(\"coffee-script\").run(system.args);'" + LAUNCHER = "narwhal -p #{ROOT} -e 'require(\"coffee-script\").run(system.args);'" # Run the CommandLine off the contents of ARGV. def initialize @@ -141,7 +143,7 @@ def compile(script, source='error') options[:no_wrap] = true if @options[:no_wrap] options[:globals] = true if @options[:globals] CoffeeScript.compile(script, options) - rescue CoffeeScript::ParseError, SyntaxError => e + rescue CoffeeScript::ParseError => e STDERR.puts "#{source}: #{e.message}" exit(1) unless @options[:watch] nil @@ -159,7 +161,7 @@ def path_for(source) # Install the CoffeeScript TextMate bundle to ~/Library. def install_bundle bundle_dir = File.expand_path('~/Library/Application Support/TextMate/Bundles/') - FileUtils.cp_r(File.dirname(__FILE__) + '/CoffeeScript.tmbundle', bundle_dir) + FileUtils.cp_r("#{ROOT}/extras/CoffeeScript.tmbundle", bundle_dir) end # Use OptionParser for all the options. diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index 1cb1337ec8..174a498dcc 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -4,8 +4,9 @@ class Parser token IF ELSE UNLESS token NUMBER STRING REGEX token TRUE FALSE YES NO ON OFF -token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS -token CODE PARAM NEW RETURN +token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS SOAK_ACCESS +token CODE PARAM_START PARAM PARAM_END NEW RETURN +token CALL_START CALL_END INDEX_START INDEX_END token TRY CATCH FINALLY THROW token BREAK CONTINUE token FOR IN OF BY WHEN WHILE @@ -16,13 +17,12 @@ token ARGUMENTS token NEWLINE token COMMENT token JS -token THIS token INDENT OUTDENT # Declare order of operations. prechigh left '?' - nonassoc UMINUS NOT '!' '!!' '~' '++' '--' + nonassoc UMINUS UPLUS NOT '!' '!!' '~' '++' '--' left '*' '/' '%' left '+' '-' left '<<' '>>' '>>>' @@ -38,9 +38,9 @@ prechigh right WHEN LEADING_WHEN IN OF BY right THROW FOR NEW SUPER left EXTENDS - left ASSIGN '||=' '&&=' '?=' - right RETURN - right '=>' '==>' UNLESS IF ELSE WHILE + left '||=' '&&=' '?=' + right ASSIGN RETURN + right '->' '=>' UNLESS IF ELSE WHILE preclow rule @@ -141,6 +141,7 @@ rule '!' Expression { result = OpNode.new(val[0], val[1]) } | '!!' Expression { result = OpNode.new(val[0], val[1]) } | '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) } + | '+' Expression = UPLUS { result = OpNode.new(val[0], val[1]) } | NOT Expression { result = OpNode.new(val[0], val[1]) } | '~' Expression { result = OpNode.new(val[0], val[1]) } | '--' Expression { result = OpNode.new(val[0], val[1]) } @@ -201,14 +202,15 @@ rule # Function definition. Code: - ParamList FuncGlyph Block { result = CodeNode.new(val[0], val[2], val[1]) } + PARAM_START ParamList PARAM_END + FuncGlyph Block { result = CodeNode.new(val[1], val[4], val[3]) } | FuncGlyph Block { result = CodeNode.new([], val[1], val[0]) } ; # The symbols to signify functions, and bound functions. FuncGlyph: - '=>' { result = :func } - | '==>' { result = :boundfunc } + '->' { result = :func } + | '=>' { result = :boundfunc } ; # The parameters to a function definition. @@ -238,20 +240,20 @@ rule | Range { result = ValueNode.new(val[0]) } | Value Accessor { result = val[0] << val[1] } | Invocation Accessor { result = ValueNode.new(val[0], [val[1]]) } - | THIS { result = ValueNode.new(ThisNode.new) } ; # 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) } + | PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], :prototype) } + | SOAK_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], :soak) } | Index { result = val[0] } - | Range { result = SliceNode.new(val[0]) } + | Slice { result = SliceNode.new(val[0]) } ; # Indexing into an object or array. Index: - "[" Expression "]" { result = IndexNode.new(val[1]) } + INDEX_START Expression INDEX_END { result = IndexNode.new(val[1]) } ; # An object literal. @@ -290,13 +292,12 @@ rule # The list of arguments to a function invocation. Arguments: - "(" ArgList ")" { result = val[1] } - | "(" ArgList ")" Code { result = val[1] << val[3] } + CALL_START ArgList CALL_END { result = val[1] } ; # Calling super. Super: - SUPER "(" ArgList ")" { result = CallNode.new(Value.new('super'), val[2]) } + SUPER CALL_START ArgList CALL_END { result = CallNode.new(Value.new('super'), val[2]) } ; # The range literal. @@ -307,6 +308,14 @@ rule "." "." "." Expression "]" { result = RangeNode.new(val[1], val[5], true) } ; + # The slice literal. + Slice: + INDEX_START Expression "." "." + Expression INDEX_END { result = RangeNode.new(val[1], val[4]) } + | INDEX_START Expression "." "." "." + Expression INDEX_END { result = RangeNode.new(val[1], val[5], true) } + ; + # The array literal. Array: "[" ArgList "]" { result = ArrayNode.new(val[1]) } diff --git a/lib/coffee_script/lexer.rb b/lib/coffee_script/lexer.rb index dad8b3d777..ecb56021ba 100644 --- a/lib/coffee_script/lexer.rb +++ b/lib/coffee_script/lexer.rb @@ -16,19 +16,18 @@ class Lexer "delete", "instanceof", "typeof", "switch", "when", "super", "extends", - "arguments", - "this"] + "arguments"] # Token matching regexes. 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 - HEREDOC = /\A("{6}|'{6}|"{3}\n?(.*?)\n?(\s*)"{3}|'{3}\n?(.*?)\n?(\s*)'{3})/m + HEREDOC = /\A("{6}|'{6}|"{3}\n?(.*?)\n?([ \t]*)"{3}|'{3}\n?(.*?)\n?([ \t]*)'{3})/m JS = /\A(``|`(.*?)([^\\]|\\\\)`)/m OPERATOR = /\A([+\*&|\/\-%=<>:!?]+)/ WHITESPACE = /\A([ \t]+)/ COMMENT = /\A(((\n?[ \t]*)?#.*$)+)/ - CODE = /\A(=?=>)/ + CODE = /\A((-|=)>)/ REGEX = /\A(\/(.*?)([^\\]|\\\\)\/[imgy]{0,4})/ MULTI_DENT = /\A((\n([ \t]*))+)(\.)?/ LAST_DENT = /\n([ \t]*)/ @@ -37,10 +36,10 @@ class Lexer # Token cleaning regexes. JS_CLEANER = /(\A`|`\Z)/ MULTILINER = /\n/ - STRING_NEWLINES = /\n\s*/ - COMMENT_CLEANER = /(^\s*#|\n\s*$)/ + STRING_NEWLINES = /\n[ \t]*/ + COMMENT_CLEANER = /(^[ \t]*#|\n[ \t]*$)/ NO_NEWLINE = /\A([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)\Z/ - HEREDOC_INDENT = /^\s+/ + HEREDOC_INDENT = /^[ \t]+/ # Tokens which a regular expression will never immediately follow, but which # a division operator might. @@ -48,9 +47,12 @@ class Lexer NOT_REGEX = [ :IDENTIFIER, :NUMBER, :REGEX, :STRING, ')', '++', '--', ']', '}', - :FALSE, :NULL, :THIS, :TRUE + :FALSE, :NULL, :TRUE ] + # Tokens which could legitimately be invoked or indexed. + CALLABLE = [:IDENTIFIER, :SUPER, ')', ']', '}', :STRING] + # Scan by attempting to match tokens one character at a time. Slow and steady. def tokenize(code) @code = code.chomp # Cleanup code by remove extra line breaks @@ -59,6 +61,7 @@ def tokenize(code) @indent = 0 # The current indent level. @indents = [] # The stack of all indent levels we are currently within. @tokens = [] # Collection of all parsed tokens in the form [:TOKEN_TYPE, value] + @spaced = nil # The last value that has a space following it. while @i < @code.length @chunk = @code[@i..-1] extract_next_token @@ -92,8 +95,15 @@ def identifier_token # 'if' will result in an [:IF, "if"] token. 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] && @tokens[-2][1] == '.') @tokens[-1][0] = :PROTOTYPE_ACCESS if tag == :IDENTIFIER && last_value == '::' + if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2] && @tokens[-2][1] == '.') + if @tokens[-2][0] == "?" + @tokens[-1][0] = :SOAK_ACCESS + @tokens.delete_at(-2) + else + @tokens[-1][0] = :PROPERTY_ACCESS + end + end token(tag, identifier) @i += identifier.length end @@ -157,7 +167,7 @@ def indent_token @line += indent.scan(MULTILINER).size @i += indent.size next_character = @chunk[MULTI_DENT, 4] - no_newlines = next_character == '.' || (last_value.to_s.match(NO_NEWLINE) && !last_value.match(CODE)) + no_newlines = next_character == '.' || (last_value.to_s.match(NO_NEWLINE) && @tokens[-2][0] != '.' && !last_value.match(CODE)) return suppress_newlines(indent) if no_newlines size = indent.scan(LAST_DENT).last.last.length return newline_token(indent) if size == @indent @@ -184,6 +194,7 @@ def outdent_token(move_out) # Matches and consumes non-meaningful whitespace. def whitespace_token return false unless whitespace = @chunk[WHITESPACE, 1] + @spaced = last_value @i += whitespace.length end @@ -208,6 +219,10 @@ def literal_token tag_parameters if value && value.match(CODE) value ||= @chunk[0,1] tag = value.match(ASSIGNMENT) ? :ASSIGN : value + if !@spaced.equal?(last_value) && CALLABLE.include?(last_tag) + tag = :CALL_START if value == '(' + tag = :INDEX_START if value == '[' + end token(tag, value) @i += value.length end @@ -235,14 +250,17 @@ def last_tag # parameter identifiers in order to avoid this. Also, parameter lists can # make use of splats. def tag_parameters + return if last_tag != ')' i = 0 loop do i -= 1 tok = @tokens[i] return if !tok - next if ['.', ','].include?(tok[0]) - return if tok[0] != :IDENTIFIER - tok[0] = :PARAM + case tok[0] + when :IDENTIFIER then tok[0] = :PARAM + when ')' then tok[0] = :PARAM_END + when '(' then return tok[0] = :PARAM_START + end end end diff --git a/lib/coffee_script/narwhal/coffee-script.coffee b/lib/coffee_script/narwhal/coffee-script.coffee index d3bc2b338e..e9f496493d 100644 --- a/lib/coffee_script/narwhal/coffee-script.coffee +++ b/lib/coffee_script/narwhal/coffee-script.coffee @@ -12,14 +12,14 @@ Readline: require('readline') coffeePath: File.path(module.path).dirname().dirname().dirname().dirname().dirname().join('bin', 'coffee') # Our general-purpose error handler. -checkForErrors: coffeeProcess => +checkForErrors: (coffeeProcess) -> return true if coffeeProcess.wait() is 0 system.stderr.print(coffeeProcess.stderr.read()) throw new Error("CoffeeScript compile error") # Run a simple REPL, round-tripping to the CoffeeScript compiler for every # command. -exports.run: args => +exports.run: (args) -> if args.length for path, i in args exports.evalCS(File.read(path)) @@ -35,24 +35,24 @@ exports.run: args => print(e) # Compile a given CoffeeScript file into JavaScript. -exports.compileFile: path => +exports.compileFile: (path) -> coffee: OS.popen([coffeePath, "--print", "--no-wrap", path]) checkForErrors(coffee) coffee.stdout.read() # Compile a string of CoffeeScript into JavaScript. -exports.compile: source, flags => +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, flags => +exports.evalCS: (source, flags) -> eval(exports.compile(source, flags)) # Make a factory for the CoffeeScript environment. -exports.makeNarwhalFactory: path => +exports.makeNarwhalFactory: (path) -> code: exports.compileFile(path) factoryText: "function(require,exports,module,system,print){" + code + "/**/\n}" if system.engine is "rhino" diff --git a/lib/coffee_script/narwhal/lib/coffee-script.js b/lib/coffee_script/narwhal/lib/coffee-script.js index 0ea0822738..b2283d0fa6 100644 --- a/lib/coffee_script/narwhal/lib/coffee-script.js +++ b/lib/coffee_script/narwhal/lib/coffee-script.js @@ -42,7 +42,7 @@ } catch (e) { return print(e); } - })()); + }).call(this)); } return __b; }; diff --git a/lib/coffee_script/narwhal/loader.coffee b/lib/coffee_script/narwhal/loader.coffee index ea6e2a0edc..5b80e7330d 100644 --- a/lib/coffee_script/narwhal/loader.coffee +++ b/lib/coffee_script/narwhal/loader.coffee @@ -6,12 +6,12 @@ factories: {} loader: { # Reload the coffee-script environment from source. - reload: topId, path => + reload: (topId, path) -> coffeescript ||= require('coffee-script') - factories[topId]: => coffeescript.makeNarwhalFactory(path) + factories[topId]: -> coffeescript.makeNarwhalFactory(path) # Ensure that the coffee-script environment is loaded. - load: topId, path => + load: (topId, path) -> factories[topId] ||= this.reload(topId, path) } diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 8269040664..3822e54388 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -55,13 +55,11 @@ def compile(o={}) closure ? compile_closure(@options) : compile_node(@options) end + # Statements converted into expressions share scope with their parent + # closure, to preserve JavaScript-style lexical scope. def compile_closure(o={}) - indent = o[:indent] - @indent = (o[:indent] = idt(1)) - pass_this = !o[:closure] && contains? {|node| node.is_a?(ThisNode) } - param = pass_this ? '__this' : '' - body = compile_node(o.merge(:return => true, :closure => true)) - "(function(#{param}) {\n#{body}\n#{indent}})(#{pass_this ? 'this' : ''})" + @indent = o[:indent] + ClosureNode.wrap(self).compile(o.merge(:shared_scope => o[:scope])) end # Quick short method for the current indentation level, plus tabbing in. @@ -335,8 +333,11 @@ class ValueNode < Node children :base, :properties attr_reader :last, :source + # Soak up undefined properties and call attempts. + SOAK = " == undefined ? undefined : " + def initialize(base, properties=[]) - @base, @properties = base, properties + @base, @properties = base, [properties].flatten end def <<(other) @@ -370,12 +371,28 @@ def statement? end def compile_node(o) - only = o.delete(:only_first) - props = only ? @properties[0...-1] : @properties - parts = [@base, props].flatten.map {|val| val.compile(o) } + soaked = false + only = o.delete(:only_first) + props = only ? @properties[0...-1] : @properties + baseline = @base.compile(o) + parts = [baseline.dup] + props.each do |prop| + if prop.is_a?(AccessorNode) && prop.soak + soaked = true + if @base.is_a?(CallNode) && prop == props.first + temp = o[:scope].free_variable + parts[-1] = "(#{temp} = #{baseline})#{SOAK}#{baseline = temp.to_s + prop.compile(o)}" + else + parts[-1] << "#{SOAK}#{baseline += prop.compile(o)}" + end + else + parts << prop.compile(o) + end + end @last = parts.last @source = parts.length > 1 ? parts[0...-1].join('') : nil - write(parts.join('')) + code = parts.join('').gsub(')())', '()))') + write(soaked ? "(#{code})" : code) end end @@ -383,9 +400,12 @@ def compile_node(o) # an accessor into the object's prototype. class AccessorNode < Node children :name + attr_reader :soak - def initialize(name, prototype=false) - @name, @prototype = name, prototype + def initialize(name, tag=nil) + @name = name + @prototype = tag == :prototype + @soak = tag == :soak end def compile_node(o) @@ -407,16 +427,6 @@ def compile_node(o) end end - # A node to represent a reference to "this". Needs to be transformed into a - # reference to the correct value of "this", when used within a closure wrapper. - class ThisNode < Node - - def compile_node(o) - write(o[:closure] ? "__this" : "this") - end - - end - # A range literal. Ranges can be used to extract portions (slices) of arrays, # or to specify a range for array comprehensions. class RangeNode < Node @@ -647,7 +657,6 @@ def compile_node(o) o[:indent] = idt(@bound ? 2 : 1) o.delete(:no_wrap) o.delete(:globals) - o.delete(:closure) if @params.last.is_a?(SplatNode) splat = @params.pop splat.index = @params.length @@ -749,6 +758,15 @@ def self.wrap(array, expressions) end end + # A faux-node used to wrap an expressions body in a closure. + class ClosureNode + def self.wrap(expressions, statement=false) + func = ParentheticalNode.new(CodeNode.new([], Expressions.wrap(expressions))) + call = CallNode.new(ValueNode.new(func, AccessorNode.new(Value.new('call'))), [Value.new('this')]) + statement ? Expressions.wrap(call) : call + end + end + # A while loop, the only sort of low-level loop exposed by CoffeeScript. From # it, all other loops can be manufactured. class WhileNode < Node @@ -808,25 +826,23 @@ def compile_node(o) rvar = scope.free_variable unless top_level svar = scope.free_variable ivar = range ? name : @index ? @index : scope.free_variable + var_part = '' + body = Expressions.wrap(@body) if range 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}++" - var_part = '' else index_var = nil source_part = "#{svar} = #{source.compile(o)};\n#{idt}" for_part = @object ? "#{ivar} in #{svar}" : "#{ivar} = 0; #{ivar} < #{svar}.length; #{ivar}++" - var_part = @name ? "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" : '' + var_part = "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" if @name + # body.unshift(AssignNode.new(@name, ValueNode.new(svar, [IndexNode.new(ivar)]))) if @name end - body = @body set_result = rvar ? "#{idt}#{rvar} = []; " : idt return_result = rvar || '' - if top_level - body = Expressions.wrap(body) - else - body = PushNode.wrap(rvar, body) - end + body = ClosureNode.wrap(body, true) if top_level && contains? {|n| n.is_a? CodeNode } + body = PushNode.wrap(rvar, body) unless top_level if o[:return] return_result = "return #{return_result}" if o[:return] o.delete(:return) diff --git a/lib/coffee_script/parse_error.rb b/lib/coffee_script/parse_error.rb index 6fbc86d127..4903deb50b 100644 --- a/lib/coffee_script/parse_error.rb +++ b/lib/coffee_script/parse_error.rb @@ -11,16 +11,16 @@ class ParseError < Racc::ParseError "\n" => 'newline' } - def initialize(token_id, value, stack) - @token_id, @value, @stack = token_id, value, stack + def initialize(token_id, value, stack=nil, message=nil) + @token_id, @value, @stack, @message = token_id, value, stack, message end def message line = @value.respond_to?(:line) ? @value.line : "END" line_part = "line #{line}:" - id_part = @token_id != @value.inspect ? ", unexpected #{@token_id.to_s.downcase}" : "" - val_part = " for #{TOKEN_MAP[@value.to_s] || "'#{@value}'"}" - "#{line_part} syntax error#{val_part}#{id_part}" + id_part = @token_id != @value.to_s ? " unexpected #{@token_id.to_s.downcase}" : "" + val_part = @message || "for #{TOKEN_MAP[@value.to_s] || "'#{@value}'"}" + "#{line_part} syntax error, #{val_part}#{id_part}" end alias_method :inspect, :message diff --git a/lib/coffee_script/parser.rb b/lib/coffee_script/parser.rb new file mode 100644 index 0000000000..9b342e4b56 --- /dev/null +++ b/lib/coffee_script/parser.rb @@ -0,0 +1,2529 @@ +# +# DO NOT MODIFY!!!! +# This file is automatically generated by Racc 1.4.6 +# from Racc grammer file "". +# + +require 'racc/parser.rb' + +module CoffeeScript + +class Parser < Racc::Parser + +module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 459) + # Lex and parse a CoffeeScript. + def parse(code) + # Uncomment the following line to enable grammar debugging, in combination + # with the -g flag in the Rake build task. + # @yydebug = true + @tokens = Lexer.new.tokenize(code) + do_parse + end + + # Retrieve the next token from the list. + def next_token + @tokens.shift + end + + # Raise a custom error class that knows about line numbers. + def on_error(error_token_id, error_value, value_stack) + raise ParseError.new(token_to_str(error_token_id), error_value, value_stack) + end + +...end grammar.y/module_eval... +##### State transition tables begin ### + +clist = [ +'128,59,136,28,31,33,38,42,47,51,56,61,64,92,93,95,175,92,93,95,284,285', +'90,276,91,296,90,59,91,59,57,65,124,130,59,155,288,144,287,261,169,158', +'143,147,164,44,155,49,54,309,193,155,173,143,147,150,153,157,143,147', +'150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122,126', +'131,134,138,141,145,148,151,154,159,121,125,129,133,137,140,166,11,174', +'13,17,191,29,262,34,11,40,198,28,31,33,38,42,47,51,56,61,64,206,207', +'203,155,1,59,100,21,25,193,-183,-183,193,43,98,291,52,57,65,66,13,17', +'206,207,6,12,59,22,59,32,35,267,44,280,49,54,13,17,188,59,189,73,4,9', +'15,19,24,13,17,49,37,46,118,261,13,17,191,13,17,191,192,49,11,278,293', +'28,31,33,38,42,47,51,56,61,64,277,13,17,188,1,2,7,21,25,275,29,59,34', +'43,40,75,52,57,65,66,100,255,13,17,6,12,114,22,98,32,35,155,44,169,49', +'54,200,201,143,147,261,73,4,9,15,19,24,100,49,155,37,46,100,100,182', +'98,-183,-183,13,17,98,98,11,49,59,28,31,33,38,42,47,51,56,61,64,92,93', +'95,108,1,2,7,21,25,90,29,91,34,43,40,49,52,57,65,66,49,49,101,101,6', +'12,183,22,184,32,35,155,44,314,49,54,13,17,-183,-183,185,73,4,9,15,19', +'24,155,284,285,37,46,13,17,143,147,150,153,157,161,123,186,11,2,7,28', +'31,33,38,42,47,51,56,61,64,92,93,95,202,1,2,7,21,25,90,29,91,34,43,40', +'155,52,57,65,66,205,75,-183,-183,6,12,118,22,217,32,35,155,44,,49,54', +',,-183,-183,,73,4,9,15,19,24,155,,,37,46,,,143,147,150,153,157,161,123', +',11,,,28,31,33,38,42,47,51,56,61,64,92,93,95,,1,2,7,21,25,90,29,91,34', +'43,40,155,52,57,65,66,,,143,147,6,12,,22,,32,35,155,44,,49,54,,,-183', +'-183,,73,4,9,15,19,24,155,,,37,46,,,143,147,150,153,157,161,123,,11', +',,28,31,33,38,42,47,51,56,61,64,92,93,95,,1,2,7,21,25,90,29,91,34,43', +'40,155,52,57,65,66,,,-183,-183,6,12,,22,,32,35,155,44,,49,54,,,-183', +'-183,,73,4,9,15,19,24,155,,,37,46,,,143,147,150,153,157,,,,11,,,28,31', +'33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,', +',,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,', +',,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,', +'52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37', +'46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29', +',34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15', +'19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2', +'7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,', +',,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61', +'64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44', +',49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47', +'51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22', +',32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31', +'33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,', +',,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,', +',,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,', +'52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37', +'46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29', +',34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15', +'19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2', +'7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,106', +',,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28', +'31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66', +',,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,', +',,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40', +',52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,', +'37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,', +'29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9', +'15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1', +'2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +',,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,310,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,', +'6,12,,22,,32,35,,44,,49,54,,116,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,', +',,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,', +'52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37', +'46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29', +',34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15', +'19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2', +'7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,', +',,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61', +'64,300,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28', +'31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66', +',,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,', +',,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40', +',52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,', +'37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,', +'29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9', +'15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1', +'2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +',,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,272,,,,,73,4,9,15,19,24,155,,,37,46,,,143,147', +'150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122,126', +'131,134,,,,,,2,7,13,17,,29,,34,11,40,,28,31,33,38,42,47,51,56,61,64', +',,,,1,,,21,25,,,,,43,,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,', +',,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61', +'64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44', +',49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47', +'51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22', +',32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31', +'33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,', +',,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,', +',,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,', +'52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37', +'46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29', +',34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15', +'19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2', +'7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,', +',,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61', +'64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44', +',49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47', +'51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22', +',32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31', +'33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,', +',,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,', +',,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,', +'52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37', +'46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29', +',34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,106,,,,,73,4,9', +'15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1', +'2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +',,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28', +'31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66', +',,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,', +',,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40', +',52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,', +'37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,', +'29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9', +'15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1', +'2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +',,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28', +'31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66', +',,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,', +',,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40', +',52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,', +'37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,', +'29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9', +'15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1', +'2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +'106,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51', +'56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32', +'35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33', +'38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,', +'6,12,,22,,32,35,,44,,49,54,59,,,,,73,4,9,15,19,24,155,,,37,46,,,143', +'147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122', +'126,131,134,,,,,,2,7,13,17,,29,,34,11,40,,28,31,33,38,42,47,51,56,61', +'64,,,,,1,,,21,25,,,,,43,,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +',,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28', +'31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66', +',,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,', +',,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40', +',52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,', +'37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,', +'29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9', +'15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1', +'2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54', +',,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56', +'61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35', +',44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28,31,33,38', +'42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,6,12', +',22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,,,,,11,,,28', +'31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66', +',,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,,,', +',,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,,29,,34,43,40', +',52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,', +'37,46,,,,,,,,,,,11,,,28,31,33,38,42,47,51,56,61,64,,,,,1,2,7,21,25,', +'29,,34,43,40,,52,57,65,66,,,,,6,12,,22,,32,35,,44,,49,54,,128,,136,', +'73,4,9,15,19,24,155,,,37,46,,,143,147,150,153,157,161,123,127,132,135', +'139,142,146,,,124,130,,,,144,,,,158,,2,7,,,,29,,34,155,40,,,,,,143,147', +'150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122,126', +'131,134,138,141,145,148,151,154,159,121,125,129,133,137,140,128,,136', +'155,,,,,,319,143,147,150,153,157,161,123,127,132,135,139,142,146,149', +'152,156,160,122,126,131,134,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,', +',,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160', +'122,126,131,134,138,141,145,148,151,154,159,121,125,129,133,137,140', +',,,,,,,,,313,28,31,33,38,42,47,51,56,61,64,,,,,1,,,21,25,,,,,43,,,52', +'57,65,,,,,,,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,,,,37,46,', +',,,28,31,33,38,42,47,51,56,61,64,,,,,1,,,21,25,,,,,43,2,7,52,57,65,29', +',34,,40,,12,,22,,32,35,,44,,49,54,,,,,,73,4,9,15,19,24,155,,,37,46,', +',143,147,150,153,157,161,123,127,132,135,,28,31,33,38,42,47,51,56,61', +'64,,,,,1,2,7,21,25,,29,,34,43,40,,52,57,65,66,,,,,,12,,22,,32,35,,44', +',49,54,,,,,,73,4,9,15,19,24,,,,37,46,,,,,28,31,33,38,42,47,51,56,61', +'64,,,,,1,,,21,25,,,,,43,2,7,52,57,65,29,,34,,40,,12,,22,,32,35,,44,', +'49,54,,,,,,73,4,9,15,,28,31,33,38,42,47,51,56,61,64,155,,,,,,,143,147', +'150,153,157,161,123,127,132,135,57,65,,,,,,2,7,,,,29,,34,44,40,155,54', +',128,,136,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152', +'156,160,122,126,131,134,,,,,,,,124,130,,,,144,,,,158,,,,,,,29,,34,155', +'40,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152', +'156,160,122,126,131,134,138,141,145,148,151,154,159,121,125,129,133', +'137,140,128,155,136,,,,,,143,147,150,153,157,161,123,127,132,135,139', +'142,146,149,152,156,160,122,126,131,134,,,,124,130,,,,144,,,,158,,,', +',,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +'149,152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125', +'129,133,137,140,128,155,136,,,,,,143,147,150,153,157,161,123,127,132', +'135,139,142,146,,,,,318,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,', +',,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160', +'122,126,131,134,138,141,145,148,151,154,159,121,125,129,133,137,140', +'128,155,136,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +'149,152,156,160,122,126,131,134,,,,124,130,,,,144,,,,158,,,,,,,,,,155', +',,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156', +'160,122,126,131,134,138,141,145,148,151,154,159,121,125,129,133,137', +'140,128,155,136,,,,,,143,147,150,153,157,161,123,127,132,135,139,142', +'146,149,152,156,160,122,126,131,134,,,,124,130,,,,144,,,,158,,,,,,,', +'178,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149', +'152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125,129', +'133,137,140,128,155,136,,,,,,143,147,150,153,157,161,123,127,132,135', +'139,142,146,149,152,156,160,122,126,131,134,,,,124,130,,,,144,,,,158', +',,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +'149,152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125', +'129,133,137,140,128,155,136,,,,,,143,147,150,153,157,161,123,127,132', +'135,139,142,146,,,,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,', +'143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160', +'122,126,131,134,138,141,145,148,151,154,159,121,125,129,133,137,140', +'128,155,136,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +',,,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153', +'157,161,123,127,132,135,139,142,146,149,152,156,160,122,126,131,134', +'138,141,145,148,151,154,159,121,125,129,133,137,140,128,155,136,,,,', +',143,147,150,153,157,161,123,127,132,135,,,,,,,,,,,,,,,124,130,,,,144', +',,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139', +'142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154,159', +'121,125,129,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,124,130', +',,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132', +'135,139,142,146,149,152,156,160,122,126,131,134,138,141,145,148,151', +'154,159,121,125,196,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,,,,,,,,,', +',,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123', +'127,132,135,139,142,146,149,152,156,160,122,126,131,134,138,141,145', +'148,151,154,159,121,125,129,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,', +',,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157', +'161,123,127,132,135,139,142,146,149,152,156,160,122,126,131,134,138', +'141,145,148,151,154,159,121,125,129,133,137,140,128,,136,,,,,,,,,,,', +',,,,,,,,,,,320,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147', +'150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122,126', +'131,134,138,141,145,148,151,154,159,121,125,129,133,137,140,128,,136', +',,,,,,,,,,,,,,,,,,,,,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,59,,155,,', +',,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156', +'160,122,126,131,134,138,141,145,148,151,154,159,121,125,129,133,137', +'140,128,,136,,,,,,,,,,,,,,,,,,,,,,,264,,,,,,,124,130,,,,144,,,,158,', +',,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +'149,152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125', +'263,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,124,130,,,,144', +',,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139', +'142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154,159', +'121,125,129,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,124,130', +',,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132', +'135,139,142,146,149,152,156,160,122,126,131,134,138,141,145,148,151', +'154,159,121,125,129,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,,,,,,,,,', +',,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123', +'127,132,135,139,142,146,149,152,156,160,122,126,131,134,138,141,145', +'148,151,154,159,121,125,129,133,137,140,128,,136,,,,,,,,,,,,,,,,,,,', +',,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157', +'161,123,127,132,135,139,142,146,149,152,156,160,122,126,131,134,138', +'141,145,148,151,154,159,121,125,129,133,137,140,128,,136,,,,,,,,,,,', +',,,,,,,,,,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,,,155,,,,,,,143,147,150', +'153,157,161,123,127,132,135,139,142,146,149,152,156,160,122,126,131', +'134,138,141,145,148,151,154,159,121,125,129,133,137,140,128,,136,,,', +',,,,,,,,,,,,,,,,,,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,59,,155,,,,,', +',143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160', +'122,126,131,134,138,141,145,148,151,154,159,121,125,129,133,137,140', +'128,,136,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,124,130,,,,144,,,,158,,,,,,,,', +',155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152', +'156,160,122,126,131,134,138,141,145,148,151,154,159,121,125,129,133', +'137,140,124,130,,,,,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161', +'123,127,132,135,139,142,146,149,152,156,160,122,126,131,134,138,141', +'145,148,151,154,159,121,125,129,133,137,140,124,130,,,,,,,,158,,,,,', +',,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149', +'152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125,129', +'133,137,140,124,130,,,,,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157', +'161,123,127,132,135,139,142,146,149,152,156,160,122,126,131,134,138', +'141,145,148,151,154,159,121,125,129,124,130,,,,,,,,158,,,,,,,,,,155', +',,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156', +'160,122,126,131,134,138,141,145,148,151,154,159,121,125,129,124,130', +',,,,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135', +'139,142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154', +'159,121,125,129,124,130,,,,,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153', +'157,161,123,127,132,135,139,142,146,149,152,156,160,122,126,131,134', +'138,141,145,148,151,154,159,121,125,129,130,,,,,,,,158,,,,,,,,,,155', +',,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156', +'160,122,126,131,134,138,141,145,148,151,154,159,121,125,129,130,,,,', +',,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139', +'142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154,159', +'121,125,129,130,,,,,,,,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161', +'123,127,132,135,139,142,146,149,152,156,160,122,126,131,134,138,141', +'145,148,151,154,159,121,125,129,130,,,,,,,,158,,,,,,,,,,155,,,,,,,143', +'147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122', +'126,131,134,138,141,145,148,151,154,159,121,125,129,130,,,,,,,,158,', +',,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +'149,152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125', +'129,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139', +'142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154,159', +'121,125,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132,135', +'139,142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154', +'159,121,125,158,,,,,,,,,,155,,,,,,,143,147,150,153,157,161,123,127,132', +'135,139,142,146,149,152,156,160,122,126,131,134,138,141,145,148,151', +'154,159,121,125,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139', +'142,146,149,152,156,160,122,126,131,134,138,141,145,148,151,154,159', +'121,125,155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146', +'149,152,156,160,122,126,131,134,138,141,145,148,151,154,159,121,125', +'155,,,,,,,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152', +'156,160,122,126,131,134,138,141,145,148,151,154,159,121,125,155,,,,', +',,143,147,150,153,157,161,123,127,132,135,139,142,146,149,152,156,160', +'122,126,131,134,138,141,145,148,151,154,159,121,125,155,,,,,,,143,147', +'150,153,157,161,123,127,132,135,139,142,146,149,152,156,160,122,126', +'131,134,138,141,145,148,151,154,159,121,125' ] + racc_action_table = arr = Array.new(9160, nil) + idx = 0 + clist.each do |str| + str.split(',', -1).each do |i| + arr[idx] = i.to_i unless i.empty? + idx += 1 + end + end + +clist = [ +'110,294,110,21,21,21,21,21,21,21,21,21,21,70,70,70,76,248,248,248,208', +'208,70,197,70,263,248,257,248,69,21,21,110,110,208,239,255,110,217,290', +'71,110,239,239,70,21,211,290,21,294,197,110,75,211,211,211,211,211,110', +'110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110', +'110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,70,169', +'76,197,197,197,21,179,21,148,21,110,148,148,148,148,148,148,148,148', +'148,148,212,212,115,112,148,277,188,148,148,105,112,112,179,148,188', +'259,148,148,148,148,308,308,119,119,148,148,278,148,169,148,148,187', +'148,205,148,148,103,103,103,201,103,148,148,148,148,148,148,115,115', +'188,148,148,66,259,105,105,105,179,179,179,105,259,4,200,259,4,4,4,4', +'4,4,4,4,4,4,199,187,187,187,4,148,148,4,4,196,148,291,148,4,148,174', +'4,4,4,4,269,173,188,188,4,4,53,4,269,4,4,236,4,171,4,4,111,111,236,236', +'178,4,4,4,4,4,4,190,178,77,4,4,29,101,92,190,77,77,258,258,29,101,6', +'269,43,6,6,6,6,6,6,6,6,6,6,249,249,249,35,6,4,4,6,6,249,4,249,4,6,4', +'190,6,6,6,6,29,101,29,101,6,6,93,6,95,6,6,83,6,307,6,6,67,67,83,83,98', +'6,6,6,6,6,6,223,286,286,6,6,62,62,223,223,223,223,223,223,223,100,9', +'175,175,9,9,9,9,9,9,9,9,9,9,27,27,27,114,9,6,6,9,9,27,6,27,6,9,6,82', +'9,9,9,9,118,1,82,82,9,9,124,9,129,9,9,79,9,,9,9,,,79,79,,9,9,9,9,9,9', +'220,,,9,9,,,220,220,220,220,220,220,220,,11,,,11,11,11,11,11,11,11,11', +'11,11,84,84,84,,11,9,9,11,11,84,9,84,9,11,9,243,11,11,11,11,,,243,243', +'11,11,,11,,11,11,87,11,,11,11,,,87,87,,11,11,11,11,11,11,215,,,11,11', +',,215,215,215,215,215,215,215,,12,,,12,12,12,12,12,12,12,12,12,12,85', +'85,85,,12,11,11,12,12,85,11,85,11,12,11,109,12,12,12,12,,,109,109,12', +'12,,12,,12,12,172,12,,12,12,,,172,172,,12,12,12,12,12,12,247,,,12,12', +',,247,247,247,247,247,,,,15,,,15,15,15,15,15,15,15,15,15,15,,,,,15,12', +'12,15,15,,12,,12,15,12,,15,15,15,15,,,,,15,15,,15,,15,15,,15,,15,15', +',,,,,15,15,15,15,15,15,,,,15,15,,,,,,,,,,,19,,,19,19,19,19,19,19,19', +'19,19,19,,,,,19,15,15,19,19,,15,,15,19,15,,19,19,19,19,,,,,19,19,,19', +',19,19,,19,,19,19,,,,,,19,19,19,19,19,19,,,,19,19,,,,,,,,,,,130,,,130', +'130,130,130,130,130,130,130,130,130,,,,,130,19,19,130,130,,19,,19,130', +'19,,130,130,130,130,,,,,130,130,,130,,130,130,,130,,130,130,,,,,,130', +'130,130,130,130,130,,,,130,130,,,,,,,,,,,22,,,22,22,22,22,22,22,22,22', +'22,22,,,,,22,130,130,22,22,,130,,130,22,130,,22,22,22,22,,,,,22,22,', +'22,,22,22,,22,,22,22,,,,,,22,22,22,22,22,22,,,,22,22,,,,,,,,,,,24,,', +'24,24,24,24,24,24,24,24,24,24,,,,,24,22,22,24,24,,22,,22,24,22,,24,24', +'24,24,,,,,24,24,,24,,24,24,,24,,24,24,,,,,,24,24,24,24,24,24,,,,24,24', +',,,,,,,,,,133,,,133,133,133,133,133,133,133,133,133,133,,,,,133,24,24', +'133,133,,24,,24,133,24,,133,133,133,133,,,,,133,133,,133,,133,133,,133', +',133,133,,,,,,133,133,133,133,133,133,,,,133,133,,,,,,,,,,,128,,,128', +'128,128,128,128,128,128,128,128,128,,,,,128,133,133,128,128,,133,,133', +'128,133,,128,128,128,128,,,,,128,128,,128,,128,128,,128,,128,128,,,', +',,128,128,128,128,128,128,,,,128,128,,,,,,,,,,,309,,,309,309,309,309', +'309,309,309,309,309,309,,,,,309,128,128,309,309,,128,,128,309,128,,309', +'309,309,309,,,,,309,309,,309,,309,309,,309,,309,309,,,,,,309,309,309', +'309,309,309,,,,309,309,,,,,,,,,,,32,,,32,32,32,32,32,32,32,32,32,32', +',,,,32,309,309,32,32,,309,,309,32,309,,32,32,32,32,,,,,32,32,,32,,32', +'32,,32,,32,32,,,,,,32,32,32,32,32,32,,,,32,32,,,,,,,,,,,34,,,34,34,34', +'34,34,34,34,34,34,34,,,,,34,32,32,34,34,,32,,32,34,32,,34,34,34,34,', +',,,34,34,,34,,34,34,,34,,34,34,34,,,,,34,34,34,34,34,34,,,,34,34,,,', +',,,,,,,127,,,127,127,127,127,127,127,127,127,127,127,,,,,127,34,34,127', +'127,,34,,34,127,34,,127,127,127,127,,,,,127,127,,127,,127,127,,127,', +'127,127,,,,,,127,127,127,127,127,127,,,,127,127,,,,,,,,,,,37,,,37,37', +'37,37,37,37,37,37,37,37,,,,,37,127,127,37,37,,127,,127,37,127,,37,37', +'37,37,,,,,37,37,,37,,37,37,,37,,37,37,,,,,,37,37,37,37,37,37,,,,37,37', +',,,,,,,,,,40,,,40,40,40,40,40,40,40,40,40,40,,,,,40,37,37,40,40,,37', +',37,40,37,,40,40,40,40,,,,,40,40,,40,,40,40,,40,,40,40,,,,,,40,40,40', +'40,40,40,,,,40,40,,,,,,,,,,,126,,,126,126,126,126,126,126,126,126,126', +'126,,,,,126,40,40,126,126,,40,,40,126,40,,126,126,126,126,,,,,126,126', +',126,,126,126,,126,,126,126,,,,,,126,126,126,126,126,126,,,,126,126', +',,,,,,,,,,46,,,46,46,46,46,46,46,46,46,46,46,,,,,46,126,126,46,46,,126', +',126,46,126,,46,46,46,46,,,,,46,46,,46,,46,46,,46,,46,46,,,,,,46,46', +'46,46,46,46,,,,46,46,,,,,,,,,,,52,,,52,52,52,52,52,52,52,52,52,52,,', +',,52,46,46,52,52,,46,,46,52,46,,52,52,52,52,,,,,52,52,,52,,52,52,,52', +',52,52,,,,,,52,52,52,52,52,52,,,,52,52,,,,,,,,,,,296,,,296,296,296,296', +'296,296,296,296,296,296,,,,,296,52,52,296,296,,52,,52,296,52,,296,296', +'296,296,,,,,296,296,,296,,296,296,,296,,296,296,,,,,,296,296,296,296', +'296,296,,,,296,296,,,,,,,,,,,59,,,59,59,59,59,59,59,59,59,59,59,296', +',,,59,296,296,59,59,,296,,296,59,296,,59,59,59,59,,,,,59,59,,59,,59', +'59,,59,,59,59,,59,,,,59,59,59,59,59,59,,,,59,59,,,,,,,,,,,285,,,285', +'285,285,285,285,285,285,285,285,285,,,,,285,59,59,285,285,,59,,59,285', +'59,,285,285,285,285,,,,,285,285,,285,,285,285,,285,,285,285,,,,,,285', +'285,285,285,285,285,,,,285,285,,,,,,,,,,,284,,,284,284,284,284,284,284', +'284,284,284,284,,,,,284,285,285,284,284,,285,,285,284,285,,284,284,284', +'284,,,,,284,284,,284,,284,284,,284,,284,284,,,,,,284,284,284,284,284', +'284,,,,284,284,,,,,,,,,,,275,,,275,275,275,275,275,275,275,275,275,275', +',,,,275,284,284,275,275,,284,,284,275,284,,275,275,275,275,,,,,275,275', +',275,,275,275,,275,,275,275,,,,,,275,275,275,275,275,275,,,,275,275', +',,,,,,,,,,272,,,272,272,272,272,272,272,272,272,272,272,275,,,,272,275', +'275,272,272,,275,,275,272,275,,272,272,272,272,,,,,272,272,,272,,272', +'272,,272,,272,272,,,,,,272,272,272,272,272,272,,,,272,272,,,,,,,,,,', +'271,,,271,271,271,271,271,271,271,271,271,271,,,,,271,272,272,271,271', +',272,,272,271,272,,271,271,271,271,,,,,271,271,,271,,271,271,,271,,271', +'271,,,,,,271,271,271,271,271,271,,,,271,271,,,,,,,,,,,261,,,261,261', +'261,261,261,261,261,261,261,261,,,,,261,271,271,261,261,,271,,271,261', +'271,,261,261,261,261,,,,,261,261,,261,,261,261,,261,,261,261,,,,,,261', +'261,261,261,261,261,,,,261,261,,,,,,,,,,,207,,,207,207,207,207,207,207', +'207,207,207,207,,,,,207,261,261,207,207,,261,,261,207,261,,207,207,207', +'207,,,,,207,207,,207,,207,207,,207,,207,207,,,,,,207,207,207,207,207', +'207,,,,207,207,,,,,,,,,,,73,,,73,73,73,73,73,73,73,73,73,73,,,,,73,207', +'207,73,73,,207,,207,73,207,,73,73,73,73,,,,,73,73,,73,,73,73,,73,,73', +'73,,,,,,73,73,73,73,73,73,,,,73,73,,,,,,,,,,,206,,,206,206,206,206,206', +'206,206,206,206,206,,,,,206,73,73,206,206,,73,,73,206,73,,206,206,206', +'206,,,,,206,206,,206,,206,206,,206,,206,206,,,,,,206,206,206,206,206', +'206,,,,206,206,,,,,,,,,,,194,,,194,194,194,194,194,194,194,194,194,194', +',,,,194,206,206,194,194,,206,,206,194,206,,194,194,194,194,,,,,194,194', +',194,,194,194,,194,,194,194,,,,,,194,194,194,194,194,194,,,,194,194', +',,,,,,,,,,191,,,191,191,191,191,191,191,191,191,191,191,,,,,191,194', +'194,191,191,,194,,194,191,194,,191,191,191,191,,,,,191,191,,191,,191', +'191,,191,,191,191,191,,,,,191,191,191,191,191,191,232,,,191,191,,,232', +'232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232', +'232,232,232,,,,,,191,191,191,191,,191,,191,186,191,,186,186,186,186', +'186,186,186,186,186,186,,,,,186,,,186,186,,,,,186,,,186,186,186,186', +',,,,186,186,,186,,186,186,,186,,186,186,,,,,,186,186,186,186,186,186', +',,,186,186,,,,,,,,,,,185,,,185,185,185,185,185,185,185,185,185,185,', +',,,185,186,186,185,185,,186,,186,185,186,,185,185,185,185,,,,,185,185', +',185,,185,185,,185,,185,185,,,,,,185,185,185,185,185,185,,,,185,185', +',,,,,,,,,,166,,,166,166,166,166,166,166,166,166,166,166,,,,,166,185', +'185,166,166,,185,,185,166,185,,166,166,166,166,,,,,166,166,,166,,166', +'166,,166,,166,166,,,,,,166,166,166,166,166,166,,,,166,166,,,,,,,,,,', +'132,,,132,132,132,132,132,132,132,132,132,132,,,,,132,166,166,132,132', +',166,,166,132,166,,132,132,132,132,,,,,132,132,,132,,132,132,,132,,132', +'132,,,,,,132,132,132,132,132,132,,,,132,132,,,,,,,,,,,161,,,161,161', +'161,161,161,161,161,161,161,161,,,,,161,132,132,161,161,,132,,132,161', +'132,,161,161,161,161,,,,,161,161,,161,,161,161,,161,,161,161,,,,,,161', +'161,161,161,161,161,,,,161,161,,,,,,,,,,,160,,,160,160,160,160,160,160', +'160,160,160,160,,,,,160,161,161,160,160,,161,,161,160,161,,160,160,160', +'160,,,,,160,160,,160,,160,160,,160,,160,160,,,,,,160,160,160,160,160', +'160,,,,160,160,,,,,,,,,,,159,,,159,159,159,159,159,159,159,159,159,159', +',,,,159,160,160,159,159,,160,,160,159,160,,159,159,159,159,,,,,159,159', +',159,,159,159,,159,,159,159,,,,,,159,159,159,159,159,159,,,,159,159', +',,,,,,,,,,158,,,158,158,158,158,158,158,158,158,158,158,,,,,158,159', +'159,158,158,,159,,159,158,159,,158,158,158,158,,,,,158,158,,158,,158', +'158,,158,,158,158,,,,,,158,158,158,158,158,158,,,,158,158,,,,,,,,,,', +'157,,,157,157,157,157,157,157,157,157,157,157,,,,,157,158,158,157,157', +',158,,158,157,158,,157,157,157,157,,,,,157,157,,157,,157,157,,157,,157', +'157,,,,,,157,157,157,157,157,157,,,,157,157,,,,,,,,,,,156,,,156,156', +'156,156,156,156,156,156,156,156,,,,,156,157,157,156,156,,157,,157,156', +'157,,156,156,156,156,,,,,156,156,,156,,156,156,,156,,156,156,,,,,,156', +'156,156,156,156,156,,,,156,156,,,,,,,,,,,125,,,125,125,125,125,125,125', +'125,125,125,125,,,,,125,156,156,125,125,,156,,156,125,156,,125,125,125', +'125,,,,,125,125,,125,,125,125,,125,,125,125,,,,,,125,125,125,125,125', +'125,,,,125,125,,,,,,,,,,,90,,,90,90,90,90,90,90,90,90,90,90,,,,,90,125', +'125,90,90,,125,,125,90,125,,90,90,90,90,,,,,90,90,,90,,90,90,,90,,90', +'90,90,,,,,90,90,90,90,90,90,,,,90,90,,,,,,,,,,,91,,,91,91,91,91,91,91', +'91,91,91,91,,,,,91,90,90,91,91,,90,,90,91,90,,91,91,91,91,,,,,91,91', +',91,,91,91,,91,,91,91,,,,,,91,91,91,91,91,91,,,,91,91,,,,,,,,,,,154', +',,154,154,154,154,154,154,154,154,154,154,,,,,154,91,91,154,154,,91', +',91,154,91,,154,154,154,154,,,,,154,154,,154,,154,154,,154,,154,154', +',,,,,154,154,154,154,154,154,,,,154,154,,,,,,,,,,,153,,,153,153,153', +'153,153,153,153,153,153,153,,,,,153,154,154,153,153,,154,,154,153,154', +',153,153,153,153,,,,,153,153,,153,,153,153,,153,,153,153,,,,,,153,153', +'153,153,153,153,,,,153,153,,,,,,,,,,,152,,,152,152,152,152,152,152,152', +'152,152,152,,,,,152,153,153,152,152,,153,,153,152,153,,152,152,152,152', +',,,,152,152,,152,,152,152,,152,,152,152,,,,,,152,152,152,152,152,152', +',,,152,152,,,,,,,,,,,151,,,151,151,151,151,151,151,151,151,151,151,', +',,,151,152,152,151,151,,152,,152,151,152,,151,151,151,151,,,,,151,151', +',151,,151,151,,151,,151,151,,,,,,151,151,151,151,151,151,,,,151,151', +',,,,,,,,,,150,,,150,150,150,150,150,150,150,150,150,150,,,,,150,151', +'151,150,150,,151,,151,150,151,,150,150,150,150,,,,,150,150,,150,,150', +'150,,150,,150,150,,,,,,150,150,150,150,150,150,,,,150,150,,,,,,,,,,', +'149,,,149,149,149,149,149,149,149,149,149,149,,,,,149,150,150,149,149', +',150,,150,149,150,,149,149,149,149,,,,,149,149,,149,,149,149,,149,,149', +'149,,,,,,149,149,149,149,149,149,,,,149,149,,,,,,,,,,,131,,,131,131', +'131,131,131,131,131,131,131,131,,,,,131,149,149,131,131,,149,,149,131', +'149,,131,131,131,131,,,,,131,131,,131,,131,131,,131,,131,131,,,,,,131', +'131,131,131,131,131,,,,131,131,,,,,,,,,,,146,,,146,146,146,146,146,146', +'146,146,146,146,,,,,146,131,131,146,146,,131,,131,146,131,,146,146,146', +'146,,,,,146,146,,146,,146,146,,146,,146,146,,,,,,146,146,146,146,146', +'146,,,,146,146,,,,,,,,,,,145,,,145,145,145,145,145,145,145,145,145,145', +',,,,145,146,146,145,145,,146,,146,145,146,,145,145,145,145,,,,,145,145', +',145,,145,145,,145,,145,145,,,,,,145,145,145,145,145,145,,,,145,145', +',,,,,,,,,,106,,,106,106,106,106,106,106,106,106,106,106,,,,,106,145', +'145,106,106,,145,,145,106,145,,106,106,106,106,,,,,106,106,,106,,106', +'106,,106,,106,106,,,,,,106,106,106,106,106,106,,,,106,106,,,,,,,,,,', +'144,,,144,144,144,144,144,144,144,144,144,144,,,,,144,106,106,144,144', +',106,,106,144,106,,144,144,144,144,,,,,144,144,,144,,144,144,,144,,144', +'144,,,,,,144,144,144,144,144,144,,,,144,144,,,,,,,,,,,108,,,108,108', +'108,108,108,108,108,108,108,108,,,,,108,144,144,108,108,,144,,144,108', +'144,,108,108,108,108,,,,,108,108,,108,,108,108,,108,,108,108,108,,,', +',108,108,108,108,108,108,,,,108,108,,,,,,,,,,,134,,,134,134,134,134', +'134,134,134,134,134,134,,,,,134,108,108,134,134,,108,,108,134,108,,134', +'134,134,134,,,,,134,134,,134,,134,134,,134,,134,134,,,,,,134,134,134', +'134,134,134,,,,134,134,,,,,,,,,,,0,,,0,0,0,0,0,0,0,0,0,0,,,,,0,134,134', +'0,0,,134,,134,0,134,,0,0,0,0,,,,,0,0,,0,,0,0,,0,,0,0,0,,,,,0,0,0,0,0', +'0,219,,,0,0,,,219,219,219,219,219,219,219,219,219,219,219,219,219,219', +'219,219,219,219,219,219,219,,,,,,0,0,0,0,,0,,0,141,0,,141,141,141,141', +'141,141,141,141,141,141,,,,,141,,,141,141,,,,,141,,,141,141,141,141', +',,,,141,141,,141,,141,141,,141,,141,141,,,,,,141,141,141,141,141,141', +',,,141,141,,,,,,,,,,,140,,,140,140,140,140,140,140,140,140,140,140,', +',,,140,141,141,140,140,,141,,141,140,141,,140,140,140,140,,,,,140,140', +',140,,140,140,,140,,140,140,,,,,,140,140,140,140,140,140,,,,140,140', +',,,,,,,,,,139,,,139,139,139,139,139,139,139,139,139,139,,,,,139,140', +'140,139,139,,140,,140,139,140,,139,139,139,139,,,,,139,139,,139,,139', +'139,,139,,139,139,,,,,,139,139,139,139,139,139,,,,139,139,,,,,,,,,,', +'138,,,138,138,138,138,138,138,138,138,138,138,,,,,138,139,139,138,138', +',139,,139,138,139,,138,138,138,138,,,,,138,138,,138,,138,138,,138,,138', +'138,,,,,,138,138,138,138,138,138,,,,138,138,,,,,,,,,,,137,,,137,137', +'137,137,137,137,137,137,137,137,,,,,137,138,138,137,137,,138,,138,137', +'138,,137,137,137,137,,,,,137,137,,137,,137,137,,137,,137,137,,,,,,137', +'137,137,137,137,137,,,,137,137,,,,,,,,,,,117,,,117,117,117,117,117,117', +'117,117,117,117,,,,,117,137,137,117,117,,137,,137,117,137,,117,117,117', +'117,,,,,117,117,,117,,117,117,,117,,117,117,,,,,,117,117,117,117,117', +'117,,,,117,117,,,,,,,,,,,136,,,136,136,136,136,136,136,136,136,136,136', +',,,,136,117,117,136,136,,117,,117,136,117,,136,136,136,136,,,,,136,136', +',136,,136,136,,136,,136,136,,,,,,136,136,136,136,136,136,,,,136,136', +',,,,,,,,,,135,,,135,135,135,135,135,135,135,135,135,135,,,,,135,136', +'136,135,135,,136,,136,135,136,,135,135,135,135,,,,,135,135,,135,,135', +'135,,135,,135,135,,,,,,135,135,135,135,135,135,,,,135,135,,,,,,,,,,', +'121,,,121,121,121,121,121,121,121,121,121,121,,,,,121,135,135,121,121', +',135,,135,121,135,,121,121,121,121,,,,,121,121,,121,,121,121,,121,,121', +'121,,,,,,121,121,121,121,121,121,,,,121,121,,,,,,,,,,,122,,,122,122', +'122,122,122,122,122,122,122,122,,,,,122,121,121,122,122,,121,,121,122', +'121,,122,122,122,122,,,,,122,122,,122,,122,122,,122,,122,122,,,,,,122', +'122,122,122,122,122,,,,122,122,,,,,,,,,,,123,,,123,123,123,123,123,123', +'123,123,123,123,,,,,123,122,122,123,123,,122,,122,123,122,,123,123,123', +'123,,,,,123,123,,123,,123,123,,123,,123,123,,,,,,123,123,123,123,123', +'123,,,,123,123,,,,,,,,,,,142,,,142,142,142,142,142,142,142,142,142,142', +',,,,142,123,123,142,142,,123,,123,142,123,,142,142,142,142,,,,,142,142', +',142,,142,142,,142,,142,142,,312,,312,,142,142,142,142,142,142,235,', +',142,142,,,235,235,235,235,235,235,235,235,235,235,235,235,235,,,312', +'312,,,,312,,,,312,,142,142,,,,142,,142,312,142,,,,,,312,312,312,312', +'312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312', +'312,312,312,312,312,312,312,312,312,312,312,312,312,301,,301,226,,,', +',,312,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226', +'226,226,226,226,226,,301,301,,,,301,,,,301,,,,,,,,,,301,,,,,,,301,301', +'301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301', +'301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,,,,,,,,', +',301,310,310,310,310,310,310,310,310,310,310,,,,,310,,,310,310,,,,,310', +',,310,310,310,,,,,,,310,,310,,310,310,,310,,310,310,,,,,,310,310,310', +'310,310,310,,,,310,310,,,,,300,300,300,300,300,300,300,300,300,300,', +',,,300,,,300,300,,,,,300,310,310,300,300,300,310,,310,,310,,300,,300', +',300,300,,300,,300,300,,,,,,300,300,300,300,300,300,233,,,300,300,,', +'233,233,233,233,233,233,233,233,233,233,,25,25,25,25,25,25,25,25,25', +'25,,,,,25,300,300,25,25,,300,,300,25,300,,25,25,25,25,,,,,,25,,25,,25', +'25,,25,,25,25,,,,,,25,25,25,25,25,25,,,,25,25,,,,,155,155,155,155,155', +'155,155,155,155,155,,,,,155,,,155,155,,,,,155,25,25,155,155,155,25,', +'25,,25,,155,,155,,155,155,,155,,155,155,,,,,,155,155,155,155,,164,164', +'164,164,164,164,164,164,164,164,227,,,,,,,227,227,227,227,227,227,227', +'227,227,227,164,164,,,,,,155,155,,,,155,,155,164,155,229,164,,204,,204', +',229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229', +'229,229,229,229,,,,,,,,204,204,,,,204,,,,204,,,,,,,164,,164,204,164', +',,,,,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204', +'204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204', +'204,68,234,68,,,,,,234,234,234,234,234,234,234,234,234,234,234,234,234', +'234,234,234,234,234,234,234,234,,,,68,68,,,,68,,,,68,,,,,,,,,,68,,,', +',,,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68', +'68,68,68,68,68,68,68,68,68,68,68,68,311,242,311,,,,,,242,242,242,242', +'242,242,242,242,242,242,242,242,242,,,,,311,,,,,,,311,311,,,,311,,,', +'311,,,,,,,,,,311,,,,,,,311,311,311,311,311,311,311,311,311,311,311,311', +'311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311', +'311,311,311,311,311,231,222,231,,,,,,222,222,222,222,222,222,222,222', +'222,222,222,222,222,222,222,222,222,222,222,222,222,,,,231,231,,,,231', +',,,231,,,,,,,,,,231,,,,,,,231,231,231,231,231,231,231,231,231,231,231', +'231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231', +'231,231,231,231,231,231,81,214,81,,,,,,214,214,214,214,214,214,214,214', +'214,214,214,214,214,214,214,214,214,214,214,214,214,,,,81,81,,,,81,', +',,81,,,,,,,,81,,81,,,,,,,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81', +'81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,224,210,224', +',,,,,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210', +'210,210,210,210,210,,,,224,224,,,,224,,,,224,,,,,,,,,,224,,,,,,,224', +'224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224', +'224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,273', +'246,273,,,,,,246,246,246,246,246,246,246,246,246,246,246,246,246,,,', +',,,,,,,,273,273,,,,273,,,,273,,,,,,,,,,273,,,,,,,273,273,273,273,273', +'273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273', +'273,273,273,273,273,273,273,273,273,273,273,273,216,238,216,,,,,,238', +'238,238,238,238,238,238,238,238,238,238,238,238,,,,,,,,,,,,216,216,', +',,216,,,,216,,,,,,,,,,216,,,,,,,216,216,216,216,216,216,216,216,216', +'216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216', +'216,216,216,216,216,216,216,216,274,230,274,,,,,,230,230,230,230,230', +'230,230,230,230,230,,,,,,,,,,,,,,,274,274,,,,274,,,,274,,,,,,,,,,274', +',,,,,,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274', +'274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274', +'274,107,,107,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,107,107,,,,107,,,,107,,,,', +',,,,,107,,,,,,,107,107,107,107,107,107,107,107,107,107,107,107,107,107', +'107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107', +'107,107,107,316,,316,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,316,316,,,,316,,,', +'316,,,,,,,,,,316,,,,,,,316,316,316,316,316,316,316,316,316,316,316,316', +'316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316', +'316,316,316,316,316,195,,195,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,195,195,,', +',195,,,,195,,,,,,,,,,195,,,,,,,195,195,195,195,195,195,195,195,195,195', +'195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195', +'195,195,195,195,195,195,195,317,,317,,,,,,,,,,,,,,,,,,,,,,,317,,,,,', +',317,317,,,,317,,,,317,,,,,,,,,,317,,,,,,,317,317,317,317,317,317,317', +'317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317', +'317,317,317,317,317,317,317,317,317,317,78,,78,,,,,,,,,,,,,,,,,,,,,', +',,,,,,,,78,78,,,,78,,,,78,,,,,,,,78,,78,,,,,,,78,78,78,78,78,78,78,78', +'78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78', +'78,78,78,181,,181,,,,,,,,,,,,,,,,,,,,,,,181,,,,,,,181,181,,,,181,,,', +'181,,,,,,,,,,181,,,,,,,181,181,181,181,181,181,181,181,181,181,181,181', +'181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181', +'181,181,181,181,181,180,,180,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,180,180,,', +',180,,,,180,,,,,,,,,,180,,,,,,,180,180,180,180,180,180,180,180,180,180', +'180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180', +'180,180,180,180,180,180,180,265,,265,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,265', +'265,,,,265,,,,265,,,,,,,,,,265,,,,,,,265,265,265,265,265,265,265,265', +'265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265', +'265,265,265,265,265,265,265,265,265,295,,295,,,,,,,,,,,,,,,,,,,,,,,', +',,,,,,295,295,,,,295,,,,295,,,,,,,,,,295,,,,,,,295,295,295,295,295,295', +'295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295', +'295,295,295,295,295,295,295,295,295,295,295,299,,299,,,,,,,,,,,,,,,', +',,,,,,,,,,,,,,299,299,,,,299,,,,299,,,,,,,,,,299,,,,,,,299,299,299,299', +'299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299', +'299,299,299,299,299,299,299,299,299,299,299,299,299,298,,298,,,,,,,', +',,,,,,,,,,,,,,,,,,,,,,298,298,,,,298,,,,298,,,,,,,,,,298,,,,,,,298,298', +'298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298', +'298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,80,,80,', +',,,,,,,,,,,,,,,,,,,,,,,,,,,,80,80,,,,80,,,,80,,,,,,,,80,,80,,,,,,,80', +'80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80', +'80,80,80,80,80,80,80,80,80,80,266,,266,,,,,,,,,,,,,,,,,,,,,,,,,,,,,', +'266,266,,,,266,,,,266,,,,,,,,,,266,,,,,,,266,266,266,266,266,266,266', +'266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266', +'266,266,266,266,266,266,266,266,266,266,88,88,,,,,,,,88,,,,,,,,,,88', +',,,,,,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88', +'88,88,88,88,88,88,88,88,88,88,88,88,88,250,250,,,,,,,,250,,,,,,,,,,250', +',,,,,,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250', +'250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250', +'250,228,228,,,,,,,,228,,,,,,,,,,228,,,,,,,228,228,228,228,228,228,228', +'228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228', +'228,228,228,228,228,228,228,113,113,,,,,,,,113,,,,,,,,,,113,,,,,,,113', +'113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113', +'113,113,113,113,113,113,113,113,113,113,113,113,113,225,225,,,,,,,,225', +',,,,,,,,,225,,,,,,,225,225,225,225,225,225,225,225,225,225,225,225,225', +'225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225', +'225,221,221,,,,,,,,221,,,,,,,,,,221,,,,,,,221,221,221,221,221,221,221', +'221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221', +'221,221,221,221,221,221,221,305,,,,,,,,305,,,,,,,,,,305,,,,,,,305,305', +'305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305', +'305,305,305,305,305,305,305,305,305,305,305,305,304,,,,,,,,304,,,,,', +',,,,304,,,,,,,304,304,304,304,304,304,304,304,304,304,304,304,304,304', +'304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304', +'218,,,,,,,,218,,,,,,,,,,218,,,,,,,218,218,218,218,218,218,218,218,218', +'218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218', +'218,218,218,218,218,282,,,,,,,,282,,,,,,,,,,282,,,,,,,282,282,282,282', +'282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282', +'282,282,282,282,282,282,282,282,282,282,281,,,,,,,,281,,,,,,,,,,281', +',,,,,,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281', +'281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,244,,,,', +',,,,,244,,,,,,,244,244,244,244,244,244,244,244,244,244,244,244,244,244', +'244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,86,', +',,,,,,,,86,,,,,,,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86', +'86,86,86,86,86,86,86,86,86,86,86,86,86,104,,,,,,,,,,104,,,,,,,104,104', +'104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104', +'104,104,104,104,104,104,104,104,104,104,104,237,,,,,,,237,237,237,237', +'237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237', +'237,237,237,237,237,237,237,237,237,240,,,,,,,240,240,240,240,240,240', +'240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240', +'240,240,240,240,240,240,240,213,,,,,,,213,213,213,213,213,213,213,213', +'213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213', +'213,213,213,213,213,209,,,,,,,209,209,209,209,209,209,209,209,209,209', +'209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209', +'209,209,209,245,,,,,,,245,245,245,245,245,245,245,245,245,245,245,245', +'245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245', +'245' ] + racc_action_check = arr = Array.new(9160, nil) + idx = 0 + clist.each do |str| + str.split(',', -1).each do |i| + arr[idx] = i.to_i unless i.empty? + idx += 1 + end + end + +racc_action_pointer = [ + 4700, 340, nil, nil, 174, nil, 249, nil, nil, 324, + nil, 399, 474, nil, nil, 549, nil, nil, nil, 624, + nil, -2, 774, nil, 849, 6008, nil, 324, nil, 235, + nil, nil, 1149, nil, 1224, 243, nil, 1374, nil, nil, + 1449, nil, nil, 202, nil, nil, 1599, nil, nil, nil, + nil, nil, 1674, 215, nil, nil, nil, nil, nil, 1824, + nil, nil, 219, nil, nil, nil, 152, 203, 6272, -22, + -2, 37, nil, 2424, nil, -38, -5, 185, 7376, 317, + 8020, 6548, 301, 242, 399, 474, 8838, 392, 8172, nil, + 3575, 3650, 229, 276, nil, 278, nil, nil, 210, nil, + 231, 236, nil, 53, 8885, 71, 4400, 7008, 4550, 451, + -2, 196, 64, 8349, 342, 64, nil, 5176, 260, 101, + nil, 5401, 5476, 5551, 351, 3500, 1524, 1299, 999, 277, + 699, 4175, 2975, 924, 4625, 5326, 5251, 5101, 5026, 4951, + 4876, 4801, 5626, nil, 4475, 4325, 4250, nil, 99, 4100, + 4025, 3950, 3875, 3800, 3725, 6074, 3425, 3350, 3275, 3200, + 3125, 3050, nil, nil, 6130, nil, 2900, nil, nil, 91, + nil, 219, 467, 120, 184, 232, nil, nil, 188, 74, + 7560, 7468, nil, nil, nil, 2825, 2750, 93, 114, nil, + 230, 2649, nil, nil, 2574, 7192, 108, -2, nil, 159, + 163, 102, nil, nil, 6180, 133, 2499, 2349, -17, 9033, + 6590, -7, 79, 8996, 6498, 408, 6824, -52, 8631, 4709, + 333, 8463, 6406, 258, 6640, 8406, 5720, 6092, 8292, 6126, + 6866, 6456, 2658, 5942, 6222, 5635, 167, 8922, 6774, -18, + 8959, nil, 6314, 376, 8791, 9070, 6682, 483, 2, 249, + 8232, nil, nil, nil, nil, -54, nil, -24, 150, 126, + nil, 2274, nil, -65, nil, 7652, 8112, nil, nil, 203, + nil, 2199, 2124, 6732, 6916, 2049, nil, 68, 89, nil, + nil, 8743, 8687, nil, 1974, 1899, 275, nil, nil, nil, + -2, 149, nil, nil, -50, 7744, 1749, nil, 7928, 7836, + 5933, 5768, nil, nil, 8575, 8519, nil, 245, 37, 1074, + 5867, 6364, 5676, nil, nil, nil, 7100, 7284, nil, nil, + nil ] + +racc_action_default = [ + -1, -183, -97, -10, -183, -106, -183, -98, -11, -183, + -107, -183, -183, -26, -12, -183, -108, -27, -13, -183, + -109, -183, -183, -14, -183, -46, -15, -125, -28, -119, + -16, -29, -183, -31, -138, -183, -17, -183, -35, -18, + -183, -127, -36, -183, -34, -19, -183, -37, -20, -47, + -21, -38, -183, -183, -30, -22, -39, -32, -2, -183, + -23, -40, -3, -105, -104, -33, -183, -183, -5, -183, + -8, -176, -9, -183, -99, -101, -183, -48, -155, -49, + -183, -183, -53, -55, -183, -126, -56, -54, -45, -130, + -138, -183, -183, -183, -111, -183, -115, -116, -183, -44, + -183, -119, -120, -183, -57, -183, -183, -139, -138, -51, + -183, -183, -50, -152, -183, -183, -25, -7, -159, -183, + -4, -183, -183, -183, -183, -183, -183, -183, -183, -183, + -183, -183, -183, -183, -183, -183, -183, -183, -183, -183, + -183, -183, -183, -59, -183, -183, -183, -58, -183, -183, + -183, -183, -183, -183, -183, -94, -183, -183, -183, -183, + -183, -183, -96, -129, -183, -110, -183, -178, -180, -183, + -174, -176, -52, -183, -183, -183, -154, -172, -183, -183, + -139, -183, -112, -113, -114, -183, -183, -183, -183, -118, + -183, -183, -137, -145, -183, -140, -183, -183, -153, -148, + -183, -183, 321, -24, -6, -183, -183, -183, -183, -87, + -75, -64, -183, -88, -76, -65, -181, -183, -93, -77, + -66, -89, -78, -67, -182, -90, -79, -68, -91, -80, + -69, -156, -81, -70, -82, -71, -60, -84, -72, -61, + -85, -83, -73, -62, -92, -86, -74, -63, -128, -183, + -41, -177, -173, -179, -175, -183, -100, -183, -183, -183, + -167, -183, -131, -183, -117, -42, -43, -124, -121, -183, + -122, -183, -183, -141, -142, -183, -132, -183, -183, -149, + -160, -161, -162, -158, -183, -183, -157, -103, -102, -95, + -183, -183, -168, -165, -183, -146, -183, -123, -143, -144, + -103, -183, -150, -151, -164, -163, -171, -183, -169, -183, + -103, -183, -183, -133, -166, -170, -147, -183, -135, -134, + -136 ] + +racc_goto_table = [ + 58, 74, 260, 208, 67, 167, 165, 163, 77, 170, + 78, 62, 268, 79, 270, 80, 81, 99, 105, 82, + 165, 163, 119, 83, 84, 85, 86, 103, 87, 88, + 53, 294, 259, 199, 252, 257, 104, 171, 107, 76, + 168, 109, nil, nil, 110, nil, nil, 111, nil, nil, + 112, nil, nil, nil, nil, nil, 113, nil, nil, nil, + nil, nil, 117, nil, nil, nil, nil, 120, nil, nil, + 115, nil, nil, 162, 179, nil, nil, 172, nil, nil, + 212, nil, 176, 292, 177, nil, nil, nil, nil, 99, + nil, nil, 197, 297, 180, 181, 286, nil, nil, 187, + nil, nil, nil, 190, nil, 253, nil, nil, nil, 254, + 195, nil, 180, nil, 306, 117, nil, nil, nil, nil, + nil, 204, nil, nil, nil, 209, 210, 211, nil, 213, + 214, 215, 216, nil, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, nil, 231, 232, + 233, nil, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 258, 248, 249, nil, + 250, nil, nil, 251, 256, nil, 99, nil, 99, nil, + nil, nil, nil, nil, 165, 163, nil, 190, 269, 265, + 266, 271, nil, nil, nil, 273, nil, nil, 274, nil, + nil, nil, nil, nil, nil, 279, nil, nil, nil, nil, + 281, 282, 283, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 258, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 99, 290, nil, + nil, 289, nil, nil, nil, 295, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 298, 299, nil, 258, 301, + nil, 302, 303, nil, nil, nil, nil, nil, 304, 305, + nil, nil, nil, nil, nil, 307, nil, nil, 308, nil, + 311, nil, nil, nil, 312, nil, nil, nil, 315, nil, + nil, nil, nil, 316, 317 ] + +racc_goto_check = [ + 2, 26, 44, 42, 4, 48, 31, 37, 5, 46, + 5, 3, 23, 5, 23, 5, 5, 21, 38, 5, + 31, 37, 41, 5, 6, 32, 5, 35, 5, 5, + 1, 39, 43, 40, 45, 25, 5, 47, 5, 24, + 49, 5, nil, nil, 5, nil, nil, 4, nil, nil, + 5, nil, nil, nil, nil, nil, 5, nil, nil, nil, + nil, nil, 2, nil, nil, nil, nil, 2, nil, nil, + 3, nil, nil, 4, 38, nil, nil, 5, nil, nil, + 41, nil, 4, 44, 4, nil, nil, nil, nil, 21, + nil, nil, 38, 23, 5, 5, 42, nil, nil, 35, + nil, nil, nil, 2, nil, 48, nil, nil, nil, 46, + 5, nil, 5, nil, 44, 2, nil, nil, nil, nil, + nil, 5, nil, nil, nil, 5, 5, 5, nil, 5, + 5, 5, 5, nil, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, nil, 5, 5, + 5, nil, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 21, 6, 32, nil, + 5, nil, nil, 4, 26, nil, 21, nil, 21, nil, + nil, nil, nil, nil, 31, 37, nil, 2, 2, 5, + 5, 2, nil, nil, nil, 5, nil, nil, 5, nil, + nil, nil, nil, nil, nil, 4, nil, nil, nil, nil, + 5, 5, 4, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 21, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 21, 2, nil, + nil, 4, nil, nil, nil, 5, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 5, 5, nil, 21, 5, + nil, 4, 4, nil, nil, nil, nil, nil, 5, 5, + nil, nil, nil, nil, nil, 4, nil, nil, 4, nil, + 5, nil, nil, nil, 5, nil, nil, nil, 2, nil, + nil, nil, nil, 5, 5 ] + +racc_goto_pointer = [ + nil, 30, 0, 11, 4, 4, 3, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, -12, nil, -176, 38, -140, 0, nil, nil, nil, + nil, -64, 4, nil, nil, -2, nil, -63, -16, -230, + -78, -44, -116, -146, -176, -135, -62, -34, -66, -31 ] + +racc_goto_default = [ + nil, nil, 194, nil, nil, 68, 70, 72, 3, 8, + 14, 18, 23, 26, 30, 36, 39, 45, 48, 50, + 55, 60, 63, 102, nil, 69, nil, 5, 10, 16, + 20, 94, 27, 96, 97, nil, 41, 89, nil, nil, + nil, nil, nil, nil, nil, 71, nil, nil, nil, nil ] + +racc_reduce_table = [ + 0, 0, :racc_error, + 0, 107, :_reduce_1, + 1, 107, :_reduce_2, + 1, 107, :_reduce_3, + 2, 107, :_reduce_4, + 1, 109, :_reduce_5, + 3, 109, :_reduce_6, + 2, 109, :_reduce_7, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 3, 110, :_reduce_24, + 2, 110, :_reduce_25, + 1, 108, :_reduce_none, + 1, 108, :_reduce_none, + 1, 128, :_reduce_28, + 1, 128, :_reduce_29, + 1, 128, :_reduce_30, + 1, 128, :_reduce_31, + 1, 128, :_reduce_32, + 1, 128, :_reduce_33, + 1, 128, :_reduce_34, + 1, 128, :_reduce_35, + 1, 128, :_reduce_36, + 1, 128, :_reduce_37, + 1, 128, :_reduce_38, + 1, 128, :_reduce_39, + 1, 128, :_reduce_40, + 3, 116, :_reduce_41, + 3, 129, :_reduce_42, + 3, 129, :_reduce_43, + 1, 129, :_reduce_44, + 2, 120, :_reduce_45, + 1, 120, :_reduce_46, + 1, 127, :_reduce_47, + 2, 115, :_reduce_48, + 2, 115, :_reduce_49, + 2, 115, :_reduce_50, + 2, 115, :_reduce_51, + 2, 115, :_reduce_52, + 2, 115, :_reduce_53, + 2, 115, :_reduce_54, + 2, 115, :_reduce_55, + 2, 115, :_reduce_56, + 2, 115, :_reduce_57, + 2, 115, :_reduce_58, + 2, 115, :_reduce_59, + 3, 115, :_reduce_60, + 3, 115, :_reduce_61, + 3, 115, :_reduce_62, + 3, 115, :_reduce_63, + 3, 115, :_reduce_64, + 3, 115, :_reduce_65, + 3, 115, :_reduce_66, + 3, 115, :_reduce_67, + 3, 115, :_reduce_68, + 3, 115, :_reduce_69, + 3, 115, :_reduce_70, + 3, 115, :_reduce_71, + 3, 115, :_reduce_72, + 3, 115, :_reduce_73, + 3, 115, :_reduce_74, + 3, 115, :_reduce_75, + 3, 115, :_reduce_76, + 3, 115, :_reduce_77, + 3, 115, :_reduce_78, + 3, 115, :_reduce_79, + 3, 115, :_reduce_80, + 3, 115, :_reduce_81, + 3, 115, :_reduce_82, + 3, 115, :_reduce_83, + 3, 115, :_reduce_84, + 3, 115, :_reduce_85, + 3, 115, :_reduce_86, + 3, 115, :_reduce_87, + 3, 115, :_reduce_88, + 3, 115, :_reduce_89, + 3, 115, :_reduce_90, + 3, 115, :_reduce_91, + 3, 115, :_reduce_92, + 3, 115, :_reduce_93, + 2, 126, :_reduce_94, + 5, 114, :_reduce_95, + 2, 114, :_reduce_96, + 1, 131, :_reduce_97, + 1, 131, :_reduce_98, + 1, 130, :_reduce_99, + 3, 130, :_reduce_100, + 1, 132, :_reduce_none, + 4, 132, :_reduce_102, + 4, 125, :_reduce_103, + 1, 112, :_reduce_104, + 1, 112, :_reduce_105, + 1, 112, :_reduce_106, + 1, 112, :_reduce_107, + 1, 112, :_reduce_108, + 1, 112, :_reduce_109, + 2, 112, :_reduce_110, + 2, 112, :_reduce_111, + 2, 137, :_reduce_112, + 2, 137, :_reduce_113, + 2, 137, :_reduce_114, + 1, 137, :_reduce_115, + 1, 137, :_reduce_116, + 3, 139, :_reduce_117, + 3, 134, :_reduce_118, + 0, 141, :_reduce_119, + 1, 141, :_reduce_120, + 3, 141, :_reduce_121, + 3, 141, :_reduce_122, + 4, 141, :_reduce_123, + 3, 141, :_reduce_124, + 1, 113, :_reduce_125, + 2, 113, :_reduce_126, + 1, 113, :_reduce_127, + 3, 124, :_reduce_128, + 2, 138, :_reduce_129, + 2, 138, :_reduce_130, + 3, 143, :_reduce_131, + 4, 142, :_reduce_132, + 6, 136, :_reduce_133, + 7, 136, :_reduce_134, + 6, 140, :_reduce_135, + 7, 140, :_reduce_136, + 3, 133, :_reduce_137, + 0, 144, :_reduce_138, + 1, 144, :_reduce_139, + 2, 144, :_reduce_140, + 3, 144, :_reduce_141, + 3, 144, :_reduce_142, + 4, 144, :_reduce_143, + 4, 144, :_reduce_144, + 2, 144, :_reduce_145, + 1, 145, :_reduce_146, + 3, 145, :_reduce_147, + 3, 118, :_reduce_148, + 4, 118, :_reduce_149, + 5, 118, :_reduce_150, + 3, 146, :_reduce_151, + 2, 119, :_reduce_152, + 3, 135, :_reduce_153, + 3, 121, :_reduce_154, + 2, 121, :_reduce_155, + 3, 121, :_reduce_156, + 4, 122, :_reduce_157, + 4, 122, :_reduce_158, + 1, 147, :_reduce_159, + 3, 147, :_reduce_160, + 2, 148, :_reduce_161, + 2, 148, :_reduce_162, + 3, 148, :_reduce_163, + 3, 148, :_reduce_164, + 5, 123, :_reduce_165, + 7, 123, :_reduce_166, + 1, 149, :_reduce_167, + 2, 149, :_reduce_168, + 3, 150, :_reduce_169, + 4, 150, :_reduce_170, + 3, 150, :_reduce_171, + 3, 151, :_reduce_172, + 2, 152, :_reduce_173, + 1, 153, :_reduce_174, + 2, 153, :_reduce_175, + 0, 154, :_reduce_176, + 2, 154, :_reduce_177, + 1, 155, :_reduce_178, + 2, 155, :_reduce_179, + 2, 117, :_reduce_180, + 3, 117, :_reduce_181, + 3, 117, :_reduce_182 ] + +racc_reduce_n = 183 + +racc_shift_n = 321 + +racc_token_table = { + false => 0, + :error => 1, + :IF => 2, + :ELSE => 3, + :UNLESS => 4, + :NUMBER => 5, + :STRING => 6, + :REGEX => 7, + :TRUE => 8, + :FALSE => 9, + :YES => 10, + :NO => 11, + :ON => 12, + :OFF => 13, + :IDENTIFIER => 14, + :PROPERTY_ACCESS => 15, + :PROTOTYPE_ACCESS => 16, + :SOAK_ACCESS => 17, + :CODE => 18, + :PARAM_START => 19, + :PARAM => 20, + :PARAM_END => 21, + :NEW => 22, + :RETURN => 23, + :CALL_START => 24, + :CALL_END => 25, + :INDEX_START => 26, + :INDEX_END => 27, + :TRY => 28, + :CATCH => 29, + :FINALLY => 30, + :THROW => 31, + :BREAK => 32, + :CONTINUE => 33, + :FOR => 34, + :IN => 35, + :OF => 36, + :BY => 37, + :WHEN => 38, + :WHILE => 39, + :SWITCH => 40, + :LEADING_WHEN => 41, + :DELETE => 42, + :INSTANCEOF => 43, + :TYPEOF => 44, + :SUPER => 45, + :EXTENDS => 46, + :ARGUMENTS => 47, + :NEWLINE => 48, + :COMMENT => 49, + :JS => 50, + :INDENT => 51, + :OUTDENT => 52, + "?" => 53, + :UMINUS => 54, + :UPLUS => 55, + :NOT => 56, + "!" => 57, + "!!" => 58, + "~" => 59, + "++" => 60, + "--" => 61, + "*" => 62, + "/" => 63, + "%" => 64, + "+" => 65, + "-" => 66, + "<<" => 67, + ">>" => 68, + ">>>" => 69, + "&" => 70, + "|" => 71, + "^" => 72, + "<=" => 73, + "<" => 74, + ">" => 75, + ">=" => 76, + "==" => 77, + "!=" => 78, + :IS => 79, + :ISNT => 80, + "&&" => 81, + "||" => 82, + :AND => 83, + :OR => 84, + "-=" => 85, + "+=" => 86, + "/=" => 87, + "*=" => 88, + "%=" => 89, + "." => 90, + "||=" => 91, + "&&=" => 92, + "?=" => 93, + :ASSIGN => 94, + "->" => 95, + "=>" => 96, + "\n" => 97, + ";" => 98, + "," => 99, + "{" => 100, + "}" => 101, + "[" => 102, + "]" => 103, + "(" => 104, + ")" => 105 } + +racc_nt_base = 106 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "IF", + "ELSE", + "UNLESS", + "NUMBER", + "STRING", + "REGEX", + "TRUE", + "FALSE", + "YES", + "NO", + "ON", + "OFF", + "IDENTIFIER", + "PROPERTY_ACCESS", + "PROTOTYPE_ACCESS", + "SOAK_ACCESS", + "CODE", + "PARAM_START", + "PARAM", + "PARAM_END", + "NEW", + "RETURN", + "CALL_START", + "CALL_END", + "INDEX_START", + "INDEX_END", + "TRY", + "CATCH", + "FINALLY", + "THROW", + "BREAK", + "CONTINUE", + "FOR", + "IN", + "OF", + "BY", + "WHEN", + "WHILE", + "SWITCH", + "LEADING_WHEN", + "DELETE", + "INSTANCEOF", + "TYPEOF", + "SUPER", + "EXTENDS", + "ARGUMENTS", + "NEWLINE", + "COMMENT", + "JS", + "INDENT", + "OUTDENT", + "\"?\"", + "UMINUS", + "UPLUS", + "NOT", + "\"!\"", + "\"!!\"", + "\"~\"", + "\"++\"", + "\"--\"", + "\"*\"", + "\"/\"", + "\"%\"", + "\"+\"", + "\"-\"", + "\"<<\"", + "\">>\"", + "\">>>\"", + "\"&\"", + "\"|\"", + "\"^\"", + "\"<=\"", + "\"<\"", + "\">\"", + "\">=\"", + "\"==\"", + "\"!=\"", + "IS", + "ISNT", + "\"&&\"", + "\"||\"", + "AND", + "OR", + "\"-=\"", + "\"+=\"", + "\"/=\"", + "\"*=\"", + "\"%=\"", + "\".\"", + "\"||=\"", + "\"&&=\"", + "\"?=\"", + "ASSIGN", + "\"->\"", + "\"=>\"", + "\"\\n\"", + "\";\"", + "\",\"", + "\"{\"", + "\"}\"", + "\"[\"", + "\"]\"", + "\"(\"", + "\")\"", + "$start", + "Root", + "Terminator", + "Expressions", + "Block", + "Expression", + "Value", + "Call", + "Code", + "Operation", + "Assign", + "If", + "Try", + "Throw", + "Return", + "While", + "For", + "Switch", + "Extends", + "Splat", + "Existence", + "Comment", + "Literal", + "AssignObj", + "ParamList", + "FuncGlyph", + "Param", + "Array", + "Object", + "Parenthetical", + "Range", + "Accessor", + "Invocation", + "Index", + "Slice", + "AssignList", + "Super", + "Arguments", + "ArgList", + "SimpleArgs", + "Catch", + "ForVariables", + "ForSource", + "Whens", + "When", + "IfBlock", + "ElsIf", + "ElsIfs", + "ElseBody", + "IfEnd" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +module_eval(<<'.,.,', 'grammar.y', 49) + def _reduce_1(val, _values, result) + result = Expressions.new + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 50) + def _reduce_2(val, _values, result) + result = Expressions.new + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 51) + def _reduce_3(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 52) + def _reduce_4(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 57) + def _reduce_5(val, _values, result) + result = Expressions.wrap(val) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 58) + def _reduce_6(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 59) + def _reduce_7(val, _values, result) + result = val[0] + result + end +.,., + +# reduce 8 omitted + +# reduce 9 omitted + +# reduce 10 omitted + +# reduce 11 omitted + +# reduce 12 omitted + +# reduce 13 omitted + +# reduce 14 omitted + +# reduce 15 omitted + +# reduce 16 omitted + +# reduce 17 omitted + +# reduce 18 omitted + +# reduce 19 omitted + +# reduce 20 omitted + +# reduce 21 omitted + +# reduce 22 omitted + +# reduce 23 omitted + +module_eval(<<'.,.,', 'grammar.y', 86) + def _reduce_24(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 87) + def _reduce_25(val, _values, result) + result = Expressions.new + result + end +.,., + +# reduce 26 omitted + +# reduce 27 omitted + +module_eval(<<'.,.,', 'grammar.y', 98) + def _reduce_28(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 99) + def _reduce_29(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 100) + def _reduce_30(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 101) + def _reduce_31(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 102) + def _reduce_32(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 103) + def _reduce_33(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 104) + def _reduce_34(val, _values, result) + result = LiteralNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 105) + def _reduce_35(val, _values, result) + result = LiteralNode.new(Value.new(true)) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 106) + def _reduce_36(val, _values, result) + result = LiteralNode.new(Value.new(false)) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 107) + def _reduce_37(val, _values, result) + result = LiteralNode.new(Value.new(true)) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 108) + def _reduce_38(val, _values, result) + result = LiteralNode.new(Value.new(false)) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 109) + def _reduce_39(val, _values, result) + result = LiteralNode.new(Value.new(true)) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 110) + def _reduce_40(val, _values, result) + result = LiteralNode.new(Value.new(false)) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 115) + def _reduce_41(val, _values, result) + result = AssignNode.new(val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 120) + def _reduce_42(val, _values, result) + result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 121) + def _reduce_43(val, _values, result) + result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 122) + def _reduce_44(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 127) + def _reduce_45(val, _values, result) + result = ReturnNode.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 128) + def _reduce_46(val, _values, result) + result = ReturnNode.new(ValueNode.new(Value.new('null'))) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 133) + def _reduce_47(val, _values, result) + result = CommentNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 140) + def _reduce_48(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 141) + def _reduce_49(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 142) + def _reduce_50(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 143) + def _reduce_51(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 144) + def _reduce_52(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 145) + def _reduce_53(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 146) + def _reduce_54(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 147) + def _reduce_55(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 148) + def _reduce_56(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 149) + def _reduce_57(val, _values, result) + result = OpNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 150) + def _reduce_58(val, _values, result) + result = OpNode.new(val[1], val[0], nil, true) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 151) + def _reduce_59(val, _values, result) + result = OpNode.new(val[1], val[0], nil, true) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 153) + def _reduce_60(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 154) + def _reduce_61(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 155) + def _reduce_62(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 157) + def _reduce_63(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 158) + def _reduce_64(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 160) + def _reduce_65(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 161) + def _reduce_66(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 162) + def _reduce_67(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 164) + def _reduce_68(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 165) + def _reduce_69(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 166) + def _reduce_70(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 168) + def _reduce_71(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 169) + def _reduce_72(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 170) + def _reduce_73(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 171) + def _reduce_74(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 173) + def _reduce_75(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 174) + def _reduce_76(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 175) + def _reduce_77(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 176) + def _reduce_78(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 178) + def _reduce_79(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 179) + def _reduce_80(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 180) + def _reduce_81(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 181) + def _reduce_82(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 182) + def _reduce_83(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 184) + def _reduce_84(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 185) + def _reduce_85(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 186) + def _reduce_86(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 187) + def _reduce_87(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 188) + def _reduce_88(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 189) + def _reduce_89(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 190) + def _reduce_90(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 191) + def _reduce_91(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 193) + def _reduce_92(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 194) + def _reduce_93(val, _values, result) + result = OpNode.new(val[1], val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 199) + def _reduce_94(val, _values, result) + result = ExistenceNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 205) + def _reduce_95(val, _values, result) + result = CodeNode.new(val[1], val[4], val[3]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 206) + def _reduce_96(val, _values, result) + result = CodeNode.new([], val[1], val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 211) + def _reduce_97(val, _values, result) + result = :func + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 212) + def _reduce_98(val, _values, result) + result = :boundfunc + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 217) + def _reduce_99(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 218) + def _reduce_100(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +# reduce 101 omitted + +module_eval(<<'.,.,', 'grammar.y', 224) + def _reduce_102(val, _values, result) + result = SplatNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 229) + def _reduce_103(val, _values, result) + result = SplatNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 234) + def _reduce_104(val, _values, result) + result = ValueNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 235) + def _reduce_105(val, _values, result) + result = ValueNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 236) + def _reduce_106(val, _values, result) + result = ValueNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 237) + def _reduce_107(val, _values, result) + result = ValueNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 238) + def _reduce_108(val, _values, result) + result = ValueNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 239) + def _reduce_109(val, _values, result) + result = ValueNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 240) + def _reduce_110(val, _values, result) + result = val[0] << val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 241) + def _reduce_111(val, _values, result) + result = ValueNode.new(val[0], [val[1]]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 246) + def _reduce_112(val, _values, result) + result = AccessorNode.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 247) + def _reduce_113(val, _values, result) + result = AccessorNode.new(val[1], :prototype) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 248) + def _reduce_114(val, _values, result) + result = AccessorNode.new(val[1], :soak) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 249) + def _reduce_115(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 250) + def _reduce_116(val, _values, result) + result = SliceNode.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 255) + def _reduce_117(val, _values, result) + result = IndexNode.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 260) + def _reduce_118(val, _values, result) + result = ObjectNode.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 265) + def _reduce_119(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 266) + def _reduce_120(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 267) + def _reduce_121(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 268) + def _reduce_122(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 270) + def _reduce_123(val, _values, result) + result = val[0] << val[3] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 271) + def _reduce_124(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 276) + def _reduce_125(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 277) + def _reduce_126(val, _values, result) + result = val[1].new_instance + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 278) + def _reduce_127(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 283) + def _reduce_128(val, _values, result) + result = ExtendsNode.new(val[0], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 288) + def _reduce_129(val, _values, result) + result = CallNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 289) + def _reduce_130(val, _values, result) + result = CallNode.new(val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 294) + def _reduce_131(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 299) + def _reduce_132(val, _values, result) + result = CallNode.new(Value.new('super'), val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 305) + def _reduce_133(val, _values, result) + result = RangeNode.new(val[1], val[4]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 307) + def _reduce_134(val, _values, result) + result = RangeNode.new(val[1], val[5], true) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 313) + def _reduce_135(val, _values, result) + result = RangeNode.new(val[1], val[4]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 315) + def _reduce_136(val, _values, result) + result = RangeNode.new(val[1], val[5], true) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 320) + def _reduce_137(val, _values, result) + result = ArrayNode.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 325) + def _reduce_138(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 326) + def _reduce_139(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 327) + def _reduce_140(val, _values, result) + result = [val[1]] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 328) + def _reduce_141(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 329) + def _reduce_142(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 330) + def _reduce_143(val, _values, result) + result = val[0] << val[3] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 331) + def _reduce_144(val, _values, result) + result = val[0] << val[3] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 332) + def _reduce_145(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 337) + def _reduce_146(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 338) + def _reduce_147(val, _values, result) + result = ([val[0]] << val[2]).flatten + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 343) + def _reduce_148(val, _values, result) + result = TryNode.new(val[1], val[2][0], val[2][1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 344) + def _reduce_149(val, _values, result) + result = TryNode.new(val[1], nil, nil, val[3]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 346) + def _reduce_150(val, _values, result) + result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 351) + def _reduce_151(val, _values, result) + result = [val[1], val[2]] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 356) + def _reduce_152(val, _values, result) + result = ThrowNode.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 361) + def _reduce_153(val, _values, result) + result = ParentheticalNode.new(val[1], val[0].line) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 366) + def _reduce_154(val, _values, result) + result = WhileNode.new(val[1], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 367) + def _reduce_155(val, _values, result) + result = WhileNode.new(val[1], nil) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 368) + def _reduce_156(val, _values, result) + result = WhileNode.new(val[2], Expressions.wrap(val[0])) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 375) + def _reduce_157(val, _values, result) + result = ForNode.new(val[0], val[3], val[2][0], val[2][1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 376) + def _reduce_158(val, _values, result) + result = ForNode.new(val[3], val[2], val[1][0], val[1][1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 381) + def _reduce_159(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 382) + def _reduce_160(val, _values, result) + result = [val[0], val[2]] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 387) + def _reduce_161(val, _values, result) + result = {:source => val[1]} + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 388) + def _reduce_162(val, _values, result) + result = {:source => val[1], :object => true} + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 390) + def _reduce_163(val, _values, result) + result = val[0].merge(:filter => val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 392) + def _reduce_164(val, _values, result) + result = val[0].merge(:step => val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 398) + def _reduce_165(val, _values, result) + result = val[3].rewrite_condition(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 400) + def _reduce_166(val, _values, result) + result = val[3].rewrite_condition(val[1]).add_else(val[5]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 405) + def _reduce_167(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 406) + def _reduce_168(val, _values, result) + result = val[0] << val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 411) + def _reduce_169(val, _values, result) + result = IfNode.new(val[1], val[2], nil, {:statement => true}) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 413) + def _reduce_170(val, _values, result) + result = IfNode.new(val[1], val[2], nil, {:statement => true}) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 414) + def _reduce_171(val, _values, result) + result = val[2].add_comment(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 419) + def _reduce_172(val, _values, result) + result = IfNode.new(val[1], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 424) + def _reduce_173(val, _values, result) + result = val[1].force_statement + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 429) + def _reduce_174(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 430) + def _reduce_175(val, _values, result) + result = val[0].add_else(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 435) + def _reduce_176(val, _values, result) + result = nil + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 436) + def _reduce_177(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 441) + def _reduce_178(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 442) + def _reduce_179(val, _values, result) + result = val[0].add_else(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 447) + def _reduce_180(val, _values, result) + result = val[0].add_else(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 448) + def _reduce_181(val, _values, result) + result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true}) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 449) + def _reduce_182(val, _values, result) + result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true, :invert => true}) + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + +end # class Parser + +end diff --git a/lib/coffee_script/rewriter.rb b/lib/coffee_script/rewriter.rb index 9635ed183e..d085c8f718 100644 --- a/lib/coffee_script/rewriter.rb +++ b/lib/coffee_script/rewriter.rb @@ -6,7 +6,8 @@ module CoffeeScript class Rewriter # Tokens that must be balanced. - BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], [:INDENT, :OUTDENT]] + BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], [:INDENT, :OUTDENT], + [:PARAM_START, :PARAM_END], [:CALL_START, :CALL_END], [:INDEX_START, :INDEX_END]] # Tokens that signal the start of a balanced pair. EXPRESSION_START = BALANCED_PAIRS.map {|pair| pair.first } @@ -17,6 +18,14 @@ class Rewriter # Tokens that indicate the close of a clause of an expression. EXPRESSION_CLOSE = [:CATCH, :WHEN, :ELSE, :FINALLY] + EXPRESSION_TAIL + # Tokens pairs that, in immediate succession, indicate an implicit call. + IMPLICIT_FUNC = [:IDENTIFIER, :SUPER, ')', :CALL_END, ']', :INDEX_END] + IMPLICIT_END = [:IF, :UNLESS, :FOR, :WHILE, "\n", :OUTDENT] + IMPLICIT_CALL = [:IDENTIFIER, :NUMBER, :STRING, :JS, :REGEX, :NEW, :PARAM_START, + :TRY, :DELETE, :INSTANCEOF, :TYPEOF, :SWITCH, :ARGUMENTS, + :TRUE, :FALSE, :YES, :NO, :ON, :OFF, '!', '!!', :NOT, + '->', '=>', '[', '(', '{'] + # The inverse mappings of token pairs we're trying to fix up. INVERSES = BALANCED_PAIRS.inject({}) do |memo, pair| memo[pair.first] = pair.last @@ -26,8 +35,8 @@ class Rewriter # Single-line flavors of block expressions that have unclosed endings. # The grammar can't disambiguate them, so we insert the implicit indentation. - SINGLE_LINERS = [:ELSE, "=>", "==>", :TRY, :FINALLY, :THEN] - SINGLE_CLOSERS = ["\n", :CATCH, :FINALLY, :ELSE, :OUTDENT, :LEADING_WHEN] + SINGLE_LINERS = [:ELSE, "->", "=>", :TRY, :FINALLY, :THEN] + SINGLE_CLOSERS = ["\n", :CATCH, :FINALLY, :ELSE, :OUTDENT, :LEADING_WHEN, :PARAM_START] # Rewrite the token stream in multiple passes, one logical filter at # a time. This could certainly be changed into a single pass through the @@ -38,6 +47,8 @@ def rewrite(tokens) remove_leading_newlines remove_mid_expression_newlines move_commas_outside_outdents + close_open_calls_and_indexes + add_implicit_parentheses add_implicit_indentation ensure_balance(*BALANCED_PAIRS) rewrite_closing_parens @@ -70,7 +81,7 @@ def adjust_comments @tokens.delete_at(i + 2) @tokens.delete_at(i - 2) next 0 - elsif prev[0] == "\n" && [:INDENT, :OUTDENT].include?(after[0]) + elsif prev[0] == "\n" && [:INDENT].include?(after[0]) @tokens.delete_at(i + 2) @tokens[i - 1] = after next 1 @@ -111,6 +122,35 @@ def move_commas_outside_outdents end end + # We've tagged the opening parenthesis of a method call, and the opening + # bracket of an indexing operation. Match them with their close. + def close_open_calls_and_indexes + parens, brackets = [0], [0] + scan_tokens do |prev, token, post, i| + case token[0] + when :CALL_START then parens.push(0) + when :INDEX_START then brackets.push(0) + when '(' then parens[-1] += 1 + when '[' then brackets[-1] += 1 + when ')' + if parens.last == 0 + parens.pop + token[0] = :CALL_END + else + parens[-1] -= 1 + end + when ']' + if brackets.last == 0 + brackets.pop + token[0] = :INDEX_END + else + brackets[-1] -= 1 + end + end + next 1 + end + end + # Because our grammar is LALR(1), it can't handle some single-line # expressions that lack ending delimiters. Use the lexer to add the implicit # blocks, so it doesn't need to. @@ -119,6 +159,7 @@ def add_implicit_indentation scan_tokens do |prev, token, post, i| next 1 unless SINGLE_LINERS.include?(token[0]) && post[0] != :INDENT && !(token[0] == :ELSE && post[0] == :IF) # Elsifs shouldn't get blocks. + starter = token[0] line = token[1].line @tokens.insert(i + 1, [:INDENT, Value.new(2, line)]) idx = i + 1 @@ -126,9 +167,11 @@ def add_implicit_indentation loop do idx += 1 tok = @tokens[idx] - if !tok || SINGLE_CLOSERS.include?(tok[0]) || - (tok[0] == ')' && parens == 0) - @tokens.insert(idx, [:OUTDENT, Value.new(2, line)]) + if (!tok || SINGLE_CLOSERS.include?(tok[0]) || + (tok[0] == ')' && parens == 0)) && + !(starter == :ELSE && tok[0] == :ELSE) + insertion = @tokens[idx - 1][0] == "," ? idx - 1 : idx + @tokens.insert(insertion, [:OUTDENT, Value.new(2, line)]) break end parens += 1 if tok[0] == '(' @@ -140,25 +183,52 @@ def add_implicit_indentation end end + # Methods may be optionally called without parentheses, for simple cases. + # Insert the implicit parentheses here, so that the parser doesn't have to + # deal with them. + def add_implicit_parentheses + stack = [0] + scan_tokens do |prev, token, post, i| + stack.push(0) if token[0] == :INDENT + if token[0] == :OUTDENT + last = stack.pop + stack[-1] += last + end + if stack.last > 0 && (IMPLICIT_END.include?(token[0]) || post.nil?) + idx = token[0] == :OUTDENT ? i + 1 : i + stack.last.times { @tokens.insert(idx, [:CALL_END, Value.new(')', token[1].line)]) } + size, stack[-1] = stack[-1] + 1, 0 + next size + end + next 1 unless IMPLICIT_FUNC.include?(prev[0]) && IMPLICIT_CALL.include?(token[0]) + @tokens.insert(i, [:CALL_START, Value.new('(', token[1].line)]) + stack[-1] += 1 + next 2 + end + end + # Ensure that all listed pairs of tokens are correctly balanced throughout # the course of the token stream. def ensure_balance(*pairs) - levels = Hash.new(0) + puts "\nbefore ensure_balance: #{@tokens.inspect}" if ENV['VERBOSE'] + levels, lines = Hash.new(0), Hash.new scan_tokens do |prev, token, post, i| pairs.each do |pair| open, close = *pair levels[open] += 1 if token[0] == open levels[open] -= 1 if token[0] == close + lines[token[0]] = token[1].line raise ParseError.new(token[0], token[1], nil) if levels[open] < 0 end next 1 end unclosed = levels.detect {|k, v| v > 0 } - raise SyntaxError, "unclosed '#{unclosed[0]}'" if unclosed + sym = unclosed && unclosed[0] + raise ParseError.new(sym, Value.new(sym, lines[sym]), nil, "unclosed '#{sym}'") if unclosed end # We'd like to support syntax like this: - # el.click(event => + # el.click((event) -> # el.hide()) # In order to accomplish this, move outdents that follow closing parens # inwards, safely. The steps to accomplish this are: diff --git a/package.json b/package.json index c1d5b0d736..e891cfa1d0 100644 --- a/package.json +++ b/package.json @@ -5,5 +5,5 @@ "description": "Unfancy JavaScript", "keywords": ["javascript", "language"], "author": "Jeremy Ashkenas", - "version": "0.2.6" + "version": "0.3.0" } diff --git a/test/fixtures/execution/test_arguments.coffee b/test/fixtures/execution/test_arguments.coffee index ecaf118ab1..71a6c9c763 100644 --- a/test/fixtures/execution/test_arguments.coffee +++ b/test/fixtures/execution/test_arguments.coffee @@ -1,10 +1,10 @@ -area: x, y, x1, y1 => +area: (x, y, x1, y1) -> (x - x1) * (x - y1) x: y: 10 x1: y1: 20 -print(area(x, y, x1, y1) is 100) +print area(x, y, x1, y1) is 100 print(area(x, y, x1, y1) is 100) @@ -18,15 +18,15 @@ print(area( # Arguments are turned into arrays. -curried: => - print(area.apply(this, arguments.concat(20, 20)) is 100) +curried: -> + print area.apply(this, arguments.concat(20, 20)) is 100 -curried(10, 10) +curried 10, 10 # Arguments is not a special keyword -- it can be assigned to: -func: => +func: -> arguments: 25 arguments -print(func(100) is 25) +print func(100) is 25 diff --git a/test/fixtures/execution/test_array_comprehension.coffee b/test/fixtures/execution/test_array_comprehension.coffee index d39ce6d439..03c1e1f76b 100644 --- a/test/fixtures/execution/test_array_comprehension.coffee +++ b/test/fixtures/execution/test_array_comprehension.coffee @@ -1,15 +1,15 @@ nums: n * n for n in [1, 2, 3] when n % 2 isnt 0 results: n * 2 for n in nums -print(results.join(',') is '2,18') +print results.join(',') is '2,18' obj: {one: 1, two: 2, three: 3} names: prop + '!' for prop of obj odds: prop + '!' for prop, value of 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 @@ -17,9 +17,26 @@ evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0 num -= 2 num * -1 -print(evens.join(', ') is '4, 6, 8') +print evens.join(', ') is '4, 6, 8' + # Make sure that the "in" operator still works. -print(2 in evens) +print 2 in evens + + +# When functions are being defined within the body of a comprehension, make +# sure that their safely wrapped in a closure to preserve local variables. + +obj: {} + +methods: ['one', 'two', 'three'] + +for method in methods + name: method + obj[name]: -> + "I'm " + name +print obj.one() is "I'm one" +print obj.two() is "I'm two" +print obj.three() is "I'm three" diff --git a/test/fixtures/execution/test_assignment.coffee b/test/fixtures/execution/test_assignment.coffee index 550f7d5cfc..3fd42dd8eb 100644 --- a/test/fixtures/execution/test_assignment.coffee +++ b/test/fixtures/execution/test_assignment.coffee @@ -7,17 +7,17 @@ catch error result2: try nonexistent * missing catch error then true -print(result is true and result2 is true) +print result is true and result2 is true # Assign to conditional. -get_x: => 10 +get_x: -> 10 if x: get_x() then 100 -print(x is 10) +print x is 10 x: if get_x() then 100 -print(x is 100) \ No newline at end of file +print x is 100 \ No newline at end of file diff --git a/test/fixtures/execution/test_blocks.coffee b/test/fixtures/execution/test_blocks.coffee index a28eecc955..2efd8aa84e 100644 --- a/test/fixtures/execution/test_blocks.coffee +++ b/test/fixtures/execution/test_blocks.coffee @@ -1,4 +1,4 @@ -results: [1, 2, 3].map() x => +results: [1, 2, 3].map (x) -> x * x -print(results.join(' ') is '1 4 9') \ No newline at end of file +print results.join(' ') is '1 4 9' \ No newline at end of file diff --git a/test/fixtures/execution/test_calling_super.coffee b/test/fixtures/execution/test_calling_super.coffee index 33a59bd3e1..546744b236 100644 --- a/test/fixtures/execution/test_calling_super.coffee +++ b/test/fixtures/execution/test_calling_super.coffee @@ -1,36 +1,36 @@ -Base: => -Base::func: string => +Base: -> +Base::func: (string) -> 'zero/' + string -FirstChild: => +FirstChild: -> FirstChild extends Base -FirstChild::func: string => +FirstChild::func: (string) -> super('one/') + string -SecondChild: => +SecondChild: -> SecondChild extends FirstChild -SecondChild::func: string => +SecondChild::func: (string) -> super('two/') + string -ThirdChild: => +ThirdChild: -> this.array: [1, 2, 3] ThirdChild extends SecondChild -ThirdChild::func: string => +ThirdChild::func: (string) -> super('three/') + string -result: (new ThirdChild()).func('four') +result: (new ThirdChild()).func 'four' -print(result is 'zero/one/two/three/four') +print result is 'zero/one/two/three/four' -TopClass: arg => +TopClass: (arg) -> this.prop: 'top-' + arg -SuperClass: arg => - super('super-' + arg) +SuperClass: (arg) -> + super 'super-' + arg -SubClass: => - super('sub') +SubClass: -> + super 'sub' SuperClass extends TopClass SubClass extends SuperClass diff --git a/test/fixtures/execution/test_chained_calls.coffee b/test/fixtures/execution/test_chained_calls.coffee index d48b50db82..8f0b704307 100644 --- a/test/fixtures/execution/test_chained_calls.coffee +++ b/test/fixtures/execution/test_chained_calls.coffee @@ -1,8 +1,9 @@ -identity_wrap: x => => x +identity_wrap: (x) -> + -> x result: identity_wrap(identity_wrap(true))()() -print(result) +print result str: 'god' @@ -13,7 +14,7 @@ result: str. reverse(). reverse() -print(result.join('') is 'dog') +print result.join('') is 'dog' result: str .split('') @@ -21,4 +22,4 @@ result: str .reverse() .reverse() -print(result.join('') is 'dog') \ No newline at end of file +print result.join('') is 'dog' \ No newline at end of file diff --git a/test/fixtures/execution/test_destructuring_assignment.coffee b/test/fixtures/execution/test_destructuring_assignment.coffee index aba854a87a..3aa454c3de 100644 --- a/test/fixtures/execution/test_destructuring_assignment.coffee +++ b/test/fixtures/execution/test_destructuring_assignment.coffee @@ -3,26 +3,26 @@ b: -2 [a, b]: [b, a] -print(a is -2) -print(b is -1) +print a is -2 +print b is -1 arr: [1, 2, 3] [a, b, c]: arr -print(a is 1) -print(b is 2) -print(c is 3) +print a is 1 +print b is 2 +print c is 3 obj: {x: 10, y: 20, z: 30} {x: a, y: b, z: c}: obj -print(a is 10) -print(b is 20) -print(c is 30) +print a is 10 +print b is 20 +print c is 30 person: { @@ -42,8 +42,8 @@ person: { {name: a, family: {brother: {addresses: [one, {city: b}]}}}: person -print(a is "Bob") -print(b is "Moquasset NY, 10021") +print a is "Bob" +print b is "Moquasset NY, 10021" test: { @@ -59,4 +59,4 @@ test: { {person: {address: [ignore, addr...]}}: test -print(addr.join(', ') is "Street 101, Apt 101, City 101") \ No newline at end of file +print addr.join(', ') is "Street 101, Apt 101, City 101" \ No newline at end of file diff --git a/test/fixtures/execution/test_everything.coffee b/test/fixtures/execution/test_everything.coffee index a1ae6b8ffa..c6b54b95df 100644 --- a/test/fixtures/execution/test_everything.coffee +++ b/test/fixtures/execution/test_everything.coffee @@ -1,15 +1,15 @@ -func: => +func: -> a: 3 b: [] while a >= 0 - b.push('o') + b.push 'o' a-- c: { "text": b other: null - something_else: x => x + 5 + something_else: (x) -> x + 5 } c: 'error' unless 42 > 41 @@ -26,4 +26,4 @@ func: => c.single: c.list[1..1][0] -print(func() is '-') +print func() is '-' diff --git a/test/fixtures/execution/test_existence.coffee b/test/fixtures/execution/test_existence.coffee index 798cd5abd4..253a8bf288 100644 --- a/test/fixtures/execution/test_existence.coffee +++ b/test/fixtures/execution/test_existence.coffee @@ -12,7 +12,7 @@ a: null a ?= 10 b ?= 10 -print(a is 10 and b is 10) +print a is 10 and b is 10 # The existential operator. @@ -20,14 +20,36 @@ print(a is 10 and b is 10) z: null x: z ? "EX" -print(z is null and x is "EX") +print z is null and x is "EX" # Only evaluate once. counter: 0 -get_next_node: => +get_next_node: -> throw "up" if counter counter++ -print(if get_next_node()? then true else false) \ No newline at end of file +print(if get_next_node()? then true else false) + + +# Existence chains, soaking up undefined properties: + +obj: { + prop: "hello" +} + +print obj?.prop is "hello" + +print obj?.prop?.non?.existent?.property is undefined + + +# Soaks and caches method calls as well. + +arr: ["--", "----"] + +print arr.pop()?.length is 4 +print arr.pop()?.length is 2 +print arr.pop()?.length is undefined +print arr[0]?.length is undefined +print arr.pop()?.length?.non?.existent()?.property is undefined diff --git a/test/fixtures/execution/test_expressions.coffee b/test/fixtures/execution/test_expressions.coffee index 5472906126..9686d1a418 100644 --- a/test/fixtures/execution/test_expressions.coffee +++ b/test/fixtures/execution/test_expressions.coffee @@ -5,11 +5,11 @@ items: [1, 2, 3, "bacon", 4, 5] for item in items break if item is "bacon" -findit: items => +findit: (items) -> for item in items return item if item is "bacon" -print(findit(items) is "bacon") +print findit(items) is "bacon" # When when a closure wrapper is generated for expression conversion, make sure @@ -17,7 +17,7 @@ print(findit(items) is "bacon") obj: { num: 5 - func: => + func: -> this.result: if false 10 else @@ -26,5 +26,5 @@ obj: { this.num } -print(obj.num is obj.func()) -print(obj.num is obj.result) \ No newline at end of file +print obj.num is obj.func() +print obj.num is obj.result \ No newline at end of file diff --git a/test/fixtures/execution/test_fancy_if_statement.coffee b/test/fixtures/execution/test_fancy_if_statement.coffee index 1e7546a0a1..f71dd51193 100644 --- a/test/fixtures/execution/test_fancy_if_statement.coffee +++ b/test/fixtures/execution/test_fancy_if_statement.coffee @@ -7,4 +7,10 @@ result: if a if d true -print(result) \ No newline at end of file +print result + + +first: if false then false else second: if false then false else true + +print first +print second \ No newline at end of file diff --git a/test/fixtures/execution/test_functions.coffee b/test/fixtures/execution/test_functions.coffee index 0a5c66767a..50552ce347 100644 --- a/test/fixtures/execution/test_functions.coffee +++ b/test/fixtures/execution/test_functions.coffee @@ -1,25 +1,25 @@ x: 1 y: {} -y.x: => 3 +y.x: -> 3 -print(x is 1) -print(typeof(y.x) is 'function') -print(y.x() is 3) -print(y.x.name is 'x') +print x is 1 +print typeof(y.x) is 'function' +print y.x() is 3 +print y.x.name is 'x' # The empty function should not cause a syntax error. -=> +-> obj: { name: "Fred" - bound: => - (==> print(this.name is "Fred"))() + bound: -> + (=> print(this.name is "Fred"))() - unbound: => - (=> print(!this.name?))() + unbound: -> + (-> print(!this.name?))() } obj.unbound() @@ -29,20 +29,50 @@ obj.bound() # The named function should be cleared out before a call occurs: # Python decorator style wrapper that memoizes any function -memoize: fn => +memoize: (fn) -> cache: {} self: this - args... => + (args...) -> key: args.toString() return cache[key] if cache[key] cache[key] = fn.apply(self, args) Math: { - Add: a, b => a + b - AnonymousAdd: (a, b => a + b) - FastAdd: memoize() a, b => a + b + Add: (a, b) -> a + b + AnonymousAdd: ((a, b) -> a + b) + FastAdd: memoize (a, b) -> a + b } -print(Math.Add(5, 5) is 10) -print(Math.AnonymousAdd(10, 10) is 20) -print(Math.FastAdd(20, 20) is 40) +print Math.Add(5, 5) is 10 +print Math.AnonymousAdd(10, 10) is 20 +print Math.FastAdd(20, 20) is 40 + + +# Parens are optional on simple function calls. +print 100 > 1 if 1 > 0 +print true unless false +print true for i in [1..3] + +print_func: (f) -> print(f()) +print_func -> true + +# Optional parens can be used in a nested fashion. +call: (func) -> func() + +result: call -> + inner: call -> + Math.Add(5, 5) + +print result is 10 + + +# And even with strange things like this: + +funcs: [(x) -> x, (x) -> x * x] +result: funcs[1] 5 + +print result is 25 + +result: ("hello".slice) 3 + +print result is 'lo' \ No newline at end of file diff --git a/test/fixtures/execution/test_funky_comments.coffee b/test/fixtures/execution/test_funky_comments.coffee index 2072847e5e..9fbc030e98 100644 --- a/test/fixtures/execution/test_funky_comments.coffee +++ b/test/fixtures/execution/test_funky_comments.coffee @@ -1,5 +1,5 @@ # comment -func: => +func: -> # comment false false # comment @@ -14,4 +14,8 @@ switch 'string' when null something_else() -print(func()) +-> + code() + # comment + +print func() diff --git a/test/fixtures/execution/test_heredocs.coffee b/test/fixtures/execution/test_heredocs.coffee index b5dcaabdba..bb0becfda8 100644 --- a/test/fixtures/execution/test_heredocs.coffee +++ b/test/fixtures/execution/test_heredocs.coffee @@ -3,7 +3,7 @@ a: """ on two lines """ -print(a is "basic heredoc\non two lines") +print a is "basic heredoc\non two lines" a: ''' @@ -12,12 +12,12 @@ a: ''' c ''' -print(a is "a\n \"b\nc") +print a is "a\n \"b\nc" a: '''one-liner''' -print(a is 'one-liner') +print a is 'one-liner' a: """ @@ -25,7 +25,7 @@ a: """ here """ -print(a is "out\nhere") +print a is "out\nhere" a: ''' @@ -34,4 +34,13 @@ a: ''' c ''' -print(a is " a\n b\nc") \ No newline at end of file +print a is " a\n b\nc" + +a: ''' +a + + +b c +''' + +print a is "a\n\n\nb c" diff --git a/test/fixtures/execution/test_lexical_scope.coffee b/test/fixtures/execution/test_lexical_scope.coffee index 7f46928b5b..769b50961c 100644 --- a/test/fixtures/execution/test_lexical_scope.coffee +++ b/test/fixtures/execution/test_lexical_scope.coffee @@ -1,3 +1,10 @@ num: 1 + 2 + (a: 3) -print(num is 6) \ No newline at end of file +print num is 6 + + +result: if true + false + other: "result" + +print result is "result" and other is "result" \ No newline at end of file diff --git a/test/fixtures/execution/test_literals.coffee b/test/fixtures/execution/test_literals.coffee index 89271965f4..c462b565f1 100644 --- a/test/fixtures/execution/test_literals.coffee +++ b/test/fixtures/execution/test_literals.coffee @@ -1,37 +1,37 @@ -a: [(x => x), (x => x * x)] +a: [(x) -> x, (x) -> x * x] -print(a.length is 2) +print a.length is 2 regex: /match/i words: "I think there is a match in here." -print(!!words.match(regex)) +print !!words.match(regex) neg: (3 -4) -print(neg is -1) +print neg is -1 -func: => +func: -> return if true -print(func() is null) +print func() is null str: "\\" reg: /\\/ -print(reg(str) and str is '\\') +print reg(str) and str is '\\' i: 10 while i -= 1 -print(i is 0) +print i is 0 money$: 'dollars' -print(money$ is 'dollars') \ No newline at end of file +print money$ is 'dollars' \ No newline at end of file diff --git a/test/fixtures/execution/test_nested_comprehensions.coffee b/test/fixtures/execution/test_nested_comprehensions.coffee index ce6952d857..8f50c49082 100644 --- a/test/fixtures/execution/test_nested_comprehensions.coffee +++ b/test/fixtures/execution/test_nested_comprehensions.coffee @@ -6,6 +6,6 @@ multi_liner: single_liner: [x, y] for y in [3..5] for x in [3..5] -print(multi_liner.length is single_liner.length) -print(5 is multi_liner[2][2][1]) -print(5 is single_liner[2][2][1]) +print multi_liner.length is single_liner.length +print 5 is multi_liner[2][2][1] +print 5 is single_liner[2][2][1] diff --git a/test/fixtures/execution/test_newline_escaping.coffee b/test/fixtures/execution/test_newline_escaping.coffee index 117c228479..9e91f45290 100644 --- a/test/fixtures/execution/test_newline_escaping.coffee +++ b/test/fixtures/execution/test_newline_escaping.coffee @@ -3,4 +3,4 @@ six: 2 + 3 -print(six is 6) \ No newline at end of file +print six is 6 \ No newline at end of file diff --git a/test/fixtures/execution/test_operations.coffee b/test/fixtures/execution/test_operations.coffee index 56f57b6c79..86332804ca 100644 --- a/test/fixtures/execution/test_operations.coffee +++ b/test/fixtures/execution/test_operations.coffee @@ -1,18 +1,18 @@ # CoffeeScript's operations should be chainable, like Python's. -print(500 > 50 > 5 > -5) +print 500 > 50 > 5 > -5 -print(true is not false is true is not false) +print true is not false is true is not false -print(10 < 20 > 10) +print 10 < 20 > 10 -print(50 > 10 > 5 is parseInt('5', 10)) +print 50 > 10 > 5 is parseInt('5', 10) # Make sure that each argument is only evaluated once, even if used # more than once. i: 0 -func: => i++ +func: -> i++ -print(1 > func() < 1) +print 1 > func() < 1 diff --git a/test/fixtures/execution/test_range_comprehension.coffee b/test/fixtures/execution/test_range_comprehension.coffee index 8917550b41..947c27d204 100644 --- a/test/fixtures/execution/test_range_comprehension.coffee +++ b/test/fixtures/execution/test_range_comprehension.coffee @@ -5,16 +5,16 @@ negs: negs[0..2] result: nums.concat(negs).join(', ') -print(result is '3, 6, 9, -20, -19, -18') +print result is '3, 6, 9, -20, -19, -18' # Ensure that ranges are safe. This used to infinite loop: j = 5 result: for j in [j..(j+3)] j -print(result.join(' ') is '5 6 7 8') +print result.join(' ') is '5 6 7 8' # With range comprehensions, you can loop in steps. results: x for x in [0..25] by 5 -print(results.join(' ') is '0 5 10 15 20 25') \ No newline at end of file +print results.join(' ') is '0 5 10 15 20 25' \ No newline at end of file diff --git a/test/fixtures/execution/test_ranges_and_slices.coffee b/test/fixtures/execution/test_ranges_and_slices.coffee index 3850067a48..a6a0bf18bf 100644 --- a/test/fixtures/execution/test_ranges_and_slices.coffee +++ b/test/fixtures/execution/test_ranges_and_slices.coffee @@ -5,7 +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") \ No newline at end of file +print countdown is "10 9 8 7 6 5 4 3 2 1" \ No newline at end of file diff --git a/test/fixtures/execution/test_splats.coffee b/test/fixtures/execution/test_splats.coffee index 683998d3e9..18083d894f 100644 --- a/test/fixtures/execution/test_splats.coffee +++ b/test/fixtures/execution/test_splats.coffee @@ -1,14 +1,14 @@ -func: first, second, rest... => - rest.join(' ') +func: (first, second, rest...) -> + rest.join ' ' -result: func(1, 2, 3, 4, 5) +result: func 1, 2, 3, 4, 5 -print(result is "3 4 5") +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,9 +27,9 @@ contenders: [ "Usain Bolt" ] -medalists("Mighty Mouse", contenders...) +medalists "Mighty Mouse", contenders... -print(gold is "Mighty Mouse") -print(silver is "Michael Phelps") -print(bronze is "Liu Xiang") -print(the_field.length is 8) \ No newline at end of file +print gold is "Mighty Mouse" +print silver is "Michael Phelps" +print bronze is "Liu Xiang" +print the_field.length is 8 \ No newline at end of file diff --git a/test/fixtures/execution/test_splices.coffee b/test/fixtures/execution/test_splices.coffee index 7f28d7978b..e9baf87793 100644 --- a/test/fixtures/execution/test_splices.coffee +++ b/test/fixtures/execution/test_splices.coffee @@ -1,7 +1,5 @@ - - array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] array[5..10]: [0, 0, 0] -print(array.join(' ') is '0 1 2 3 4 0 0 0') \ No newline at end of file +print array.join(' ') is '0 1 2 3 4 0 0 0' \ No newline at end of file diff --git a/test/fixtures/execution/test_switch.coffee b/test/fixtures/execution/test_switch.coffee index 35ff3c7ab8..3911f043f8 100644 --- a/test/fixtures/execution/test_switch.coffee +++ b/test/fixtures/execution/test_switch.coffee @@ -14,10 +14,9 @@ result: switch num when 11 then false else false -print(result) +print result - -func: num => +func: (num) -> switch num when 2, 4, 6 true @@ -25,7 +24,7 @@ func: num => false else false -print(func(2)) -print(func(6)) -print(!func(3)) -print(!func(8)) +print func(2) +print func(6) +print !func(3) +print !func(8) diff --git a/test/fixtures/execution/test_while.coffee b/test/fixtures/execution/test_while.coffee index 16972f1fe4..c065fe046d 100644 --- a/test/fixtures/execution/test_while.coffee +++ b/test/fixtures/execution/test_while.coffee @@ -1,17 +1,17 @@ i: 100 while i -= 1 -print(i is 0) +print i is 0 i: 5 list: while i -= 1 i * 2 -print(list.join(' ') is "8 6 4 2") +print list.join(' ') is "8 6 4 2" i: 5 list: (i * 3 while i -= 1) -print(list.join(' ') is "12 9 6 3") \ No newline at end of file +print list.join(' ') is "12 9 6 3" \ No newline at end of file diff --git a/test/fixtures/generation/each.coffee b/test/fixtures/generation/each.coffee index 89bade6171..9b76b97694 100644 --- a/test/fixtures/generation/each.coffee +++ b/test/fixtures/generation/each.coffee @@ -1,6 +1,6 @@ # The cornerstone, an each implementation. # Handles objects implementing forEach, arrays, and raw objects. -_.each: obj, iterator, context => +_.each: (obj, iterator, context) -> index: 0 try if obj.forEach diff --git a/test/fixtures/generation/each.tokens b/test/fixtures/generation/each.tokens index aa5d853e2a..70d9cff13f 100644 --- a/test/fixtures/generation/each.tokens +++ b/test/fixtures/generation/each.tokens @@ -1 +1 @@ -[[:COMMENT, [" The cornerstone, an each implementation.", " Handles objects implementing forEach, arrays, and raw objects."]], ["\n", "\n"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "each"], [:ASSIGN, ":"], [:PARAM, "obj"], [",", ","], [:PARAM, "iterator"], [",", ","], [:PARAM, "context"], ["=>", "=>"], [:INDENT, 2], [:IDENTIFIER, "index"], [:ASSIGN, ":"], [:NUMBER, "0"], ["\n", "\n"], [:TRY, "try"], [:INDENT, 2], [:IF, "if"], [:IDENTIFIER, "obj"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "forEach"], [:INDENT, 2], [:IDENTIFIER, "obj"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "forEach"], ["(", "("], [:IDENTIFIER, "iterator"], [",", ","], [:IDENTIFIER, "context"], [")", ")"], [:OUTDENT, 2], [:ELSE, "else"], [:IF, "if"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "isArray"], ["(", "("], [:IDENTIFIER, "obj"], [")", ")"], [:OR, "or"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "isArguments"], ["(", "("], [:IDENTIFIER, "obj"], [")", ")"], [:INDENT, 2], [:IDENTIFIER, "iterator"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "call"], ["(", "("], [:IDENTIFIER, "context"], [",", ","], [:IDENTIFIER, "item"], [",", ","], [:IDENTIFIER, "i"], [",", ","], [:IDENTIFIER, "obj"], [")", ")"], [:FOR, "for"], [:IDENTIFIER, "item"], [",", ","], [:IDENTIFIER, "i"], [:IN, "in"], [:IDENTIFIER, "obj"], [:OUTDENT, 2], [:ELSE, "else"], [:INDENT, 2], [:IDENTIFIER, "iterator"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "call"], ["(", "("], [:IDENTIFIER, "context"], [",", ","], [:IDENTIFIER, "obj"], ["[", "["], [:IDENTIFIER, "key"], ["]", "]"], [",", ","], [:IDENTIFIER, "key"], [",", ","], [:IDENTIFIER, "obj"], [")", ")"], [:FOR, "for"], [:IDENTIFIER, "key"], [:IN, "in"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "keys"], ["(", "("], [:IDENTIFIER, "obj"], [")", ")"], [:OUTDENT, 2], [:OUTDENT, 2], [:CATCH, "catch"], [:IDENTIFIER, "e"], [:INDENT, 2], [:THROW, "throw"], [:IDENTIFIER, "e"], [:IF, "if"], [:IDENTIFIER, "e"], [:ISNT, "isnt"], [:IDENTIFIER, "breaker"], [:OUTDENT, 2], ["\n", "\n"], [:IDENTIFIER, "obj"], [:OUTDENT, 2], ["\n", "\n"]] \ No newline at end of file +[[:COMMENT, [" The cornerstone, an each implementation.", " Handles objects implementing forEach, arrays, and raw objects."]], ["\n", "\n"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "each"], [:ASSIGN, ":"], [:PARAM_START, "("], [:PARAM, "obj"], [",", ","], [:PARAM, "iterator"], [",", ","], [:PARAM, "context"], [:PARAM_END, ")"], ["->", "->"], [:INDENT, 2], [:IDENTIFIER, "index"], [:ASSIGN, ":"], [:NUMBER, "0"], ["\n", "\n"], [:TRY, "try"], [:INDENT, 2], [:IF, "if"], [:IDENTIFIER, "obj"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "forEach"], [:INDENT, 2], [:IDENTIFIER, "obj"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "forEach"], [:CALL_START, "("], [:IDENTIFIER, "iterator"], [",", ","], [:IDENTIFIER, "context"], [:CALL_END, ")"], [:OUTDENT, 2], [:ELSE, "else"], [:IF, "if"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "isArray"], [:CALL_START, "("], [:IDENTIFIER, "obj"], [:CALL_END, ")"], [:OR, "or"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "isArguments"], [:CALL_START, "("], [:IDENTIFIER, "obj"], [:CALL_END, ")"], [:INDENT, 2], [:IDENTIFIER, "iterator"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "call"], [:CALL_START, "("], [:IDENTIFIER, "context"], [",", ","], [:IDENTIFIER, "item"], [",", ","], [:IDENTIFIER, "i"], [",", ","], [:IDENTIFIER, "obj"], [:CALL_END, ")"], [:FOR, "for"], [:IDENTIFIER, "item"], [",", ","], [:IDENTIFIER, "i"], [:IN, "in"], [:IDENTIFIER, "obj"], [:OUTDENT, 2], [:ELSE, "else"], [:INDENT, 2], [:IDENTIFIER, "iterator"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "call"], [:CALL_START, "("], [:IDENTIFIER, "context"], [",", ","], [:IDENTIFIER, "obj"], [:INDEX_START, "["], [:IDENTIFIER, "key"], [:INDEX_END, "]"], [",", ","], [:IDENTIFIER, "key"], [",", ","], [:IDENTIFIER, "obj"], [:CALL_END, ")"], [:FOR, "for"], [:IDENTIFIER, "key"], [:IN, "in"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "keys"], [:CALL_START, "("], [:IDENTIFIER, "obj"], [:CALL_END, ")"], [:OUTDENT, 2], [:OUTDENT, 2], [:CATCH, "catch"], [:IDENTIFIER, "e"], [:INDENT, 2], [:THROW, "throw"], [:IDENTIFIER, "e"], [:IF, "if"], [:IDENTIFIER, "e"], [:ISNT, "isnt"], [:IDENTIFIER, "breaker"], [:OUTDENT, 2], ["\n", "\n"], [:IDENTIFIER, "obj"], [:OUTDENT, 2], ["\n", "\n"]] \ No newline at end of file diff --git a/test/fixtures/generation/statements_as_expressions.coffee b/test/fixtures/generation/statements_as_expressions.coffee index 0541d95fe2..56baa37469 100644 --- a/test/fixtures/generation/statements_as_expressions.coffee +++ b/test/fixtures/generation/statements_as_expressions.coffee @@ -10,7 +10,7 @@ catch error 3 ) -func: x => +func: (x) -> return throw x print(x * x for x in [1..100]) \ No newline at end of file diff --git a/test/fixtures/generation/whitespace.coffee b/test/fixtures/generation/whitespace.coffee index 450fd9e5b0..781af19b6e 100644 --- a/test/fixtures/generation/whitespace.coffee +++ b/test/fixtures/generation/whitespace.coffee @@ -1,20 +1,20 @@ # test -f1: x => +f1: (x) -> x * x - f2: y => + f2: (y) -> y * x f3: 3 # Parens can close on the proper level. -elements.each(el => - el.click(event => +elements.each((el) -> + el.click((event) -> el.reset() el.show() if event.active ) ) # Or, parens can close blocks early. -elements.each(el => - el.click(event => +elements.each((el) -> + el.click((event) -> el.reset() el.show() if event.active)) \ No newline at end of file diff --git a/test/unit/test_execution.rb b/test/unit/test_execution.rb index 81db6a6d85..8eea7479b5 100644 --- a/test/unit/test_execution.rb +++ b/test/unit/test_execution.rb @@ -6,7 +6,8 @@ class ExecutionTest < Test::Unit::TestCase SOURCES = [ 'test/fixtures/execution/*.coffee', - 'examples/beautiful_code/*.coffee' + 'examples/beautiful_code/*.coffee', + 'examples/computer_science/*.coffee' ] # This is by far the most important test. It evaluates all of the diff --git a/test/unit/test_lexer.rb b/test/unit/test_lexer.rb index ec08df018c..db72a1a122 100644 --- a/test/unit/test_lexer.rb +++ b/test/unit/test_lexer.rb @@ -25,16 +25,17 @@ def test_lexing_object_literal end def test_lexing_function_definition - code = "x, y => x * y" - assert @lex.tokenize(code) == [[:PARAM, "x"], [",", ","], [:PARAM, "y"], - ["=>", "=>"], [:INDENT, 2], [:IDENTIFIER, "x"], ["*", "*"], + code = "(x, y) -> x * y" + assert @lex.tokenize(code) == [[:PARAM_START, "("], [:PARAM, "x"], + [",", ","], [:PARAM, "y"], [:PARAM_END, ")"], + ["->", "->"], [:INDENT, 2], [:IDENTIFIER, "x"], ["*", "*"], [:IDENTIFIER, "y"], [:OUTDENT, 2], ["\n", "\n"]] end def test_lexing_if_statement code = "clap_your_hands() if happy" - assert @lex.tokenize(code) == [[:IDENTIFIER, "clap_your_hands"], ["(", "("], - [")", ")"], [:IF, "if"], [:IDENTIFIER, "happy"], ["\n", "\n"]] + assert @lex.tokenize(code) == [[:IDENTIFIER, "clap_your_hands"], [:CALL_START, "("], + [:CALL_END, ")"], [:IF, "if"], [:IDENTIFIER, "happy"], ["\n", "\n"]] end def test_lexing_comment diff --git a/test/unit/test_parser.rb b/test/unit/test_parser.rb index fc0ae6aa78..1a95ae84fb 100644 --- a/test/unit/test_parser.rb +++ b/test/unit/test_parser.rb @@ -29,7 +29,7 @@ def test_parsing_an_object_literal end def test_parsing_an_function_definition - code = @par.parse("x, y => x * y").expressions.first + code = @par.parse("(x, y) -> x * y").expressions.first assert code.params == ['x', 'y'] body = code.body.expressions.first assert body.is_a?(OpNode)