diff --git a/.gitignore b/.gitignore index 2eb797553a..34de3574ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +test.coffee parser.output +test/fixtures/underscore *.gem \ No newline at end of file diff --git a/Rakefile b/Rakefile index 51f7b2a3f0..1086cefdad 100644 --- a/Rakefile +++ b/Rakefile @@ -19,7 +19,14 @@ namespace :build do desc "Compile the Narwhal interface for --interactive and --run" task :narwhal do - sh "bin/coffee lib/coffee_script/narwhal/*.coffee -o lib/coffee_script/narwhal/js" + sh "bin/coffee lib/coffee_script/narwhal/*.coffee -o lib/coffee_script/narwhal/lib/coffee-script" + sh "mv lib/coffee_script/narwhal/lib/coffee-script/coffee-script.js lib/coffee_script/narwhal/lib/coffee-script.js" + end + + desc "Compile and install the Ultraviolet syntax highlighter" + task :ultraviolet do + sh "plist2syntax lib/coffee_script/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 end @@ -30,6 +37,7 @@ task :doc do child = fork { exec "bin/coffee documentation/coffee/*.coffee -o documentation/js -w" } at_exit { Process.kill("INT", child) } Signal.trap("INT") { exit } + # `uv -t idle -s coffeescript -h examples/underscore.coffee > documentation/underscore.html` loop do mtime = File.stat(source).mtime if !@mtime || mtime > @mtime diff --git a/coffee-script.gemspec b/coffee-script.gemspec index ef684aa0a7..2f77736167 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.1.6' # Keep version in sync with coffee-script.rb - s.date = '2009-12-27' + s.version = '0.2.0' # Keep version in sync with coffee-script.rb + s.date = '2010-1-5' s.homepage = "http://jashkenas.github.com/coffee-script/" s.summary = "The CoffeeScript Compiler" @@ -22,5 +22,5 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.executables = ['coffee'] - s.files = Dir['bin/*', 'examples/*', 'lib/**/*', 'coffee-script.gemspec', 'LICENSE', 'README'] + s.files = Dir['bin/*', 'examples/*', 'lib/**/*', 'coffee-script.gemspec', 'LICENSE', 'README', 'package.json'] end \ No newline at end of file diff --git a/documentation/coffee/aliases.coffee b/documentation/coffee/aliases.coffee index f1a29e0f07..720c2081ec 100644 --- a/documentation/coffee/aliases.coffee +++ b/documentation/coffee/aliases.coffee @@ -4,4 +4,4 @@ volume: 10 if band isnt spinal_tap let_the_wild_rumpus_begin() unless answer is no -if car.speed < speed_limit then accelerate(). +if car.speed < speed_limit then accelerate() diff --git a/documentation/coffee/array_comprehensions.coffee b/documentation/coffee/array_comprehensions.coffee index ddda9319e8..3510e1fb0a 100644 --- a/documentation/coffee/array_comprehensions.coffee +++ b/documentation/coffee/array_comprehensions.coffee @@ -1,5 +1,7 @@ # Eat lunch. -lunch: food.eat() for food in ['toast', 'cheese', 'wine']. +lunch: eat(food) for food in ['toast', 'cheese', 'wine'] -# Zebra-stripe a table. -highlight(row) for row, i in table if i % 2 is 0. \ No newline at end of file +# 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 diff --git a/documentation/coffee/blocks.coffee b/documentation/coffee/blocks.coffee new file mode 100644 index 0000000000..6f31ee164c --- /dev/null +++ b/documentation/coffee/blocks.coffee @@ -0,0 +1,4 @@ +$('table.list').each() table => + $('tr.account', table).each() row => + row.show() + row.highlight() diff --git a/documentation/coffee/conditionals.coffee b/documentation/coffee/conditionals.coffee index 253d912c3b..50c18c43e1 100644 --- a/documentation/coffee/conditionals.coffee +++ b/documentation/coffee/conditionals.coffee @@ -2,8 +2,8 @@ mood: greatly_improved if singing if happy and knows_it claps_hands() - cha_cha_cha(). + cha_cha_cha() -date: if friday then sue else jill. +date: if friday then sue else jill expensive ||= do_the_math() \ No newline at end of file diff --git a/documentation/coffee/existence.coffee b/documentation/coffee/existence.coffee new file mode 100644 index 0000000000..68dc041190 --- /dev/null +++ b/documentation/coffee/existence.coffee @@ -0,0 +1 @@ +solipsism: true if mind? and not world? \ No newline at end of file diff --git a/documentation/coffee/expressions.coffee b/documentation/coffee/expressions.coffee index 0e8da6d5e9..fa0c1e3af4 100644 --- a/documentation/coffee/expressions.coffee +++ b/documentation/coffee/expressions.coffee @@ -2,8 +2,8 @@ grade: student => if student.excellent_work "A+" else if student.okay_stuff - if student.tried_hard then "B" else "B-". + if student.tried_hard then "B" else "B-" else - "C".. + "C" -eldest: if 24 > 21 then "Liz" else "Ike". \ No newline at end of file +eldest: if 24 > 21 then "Liz" else "Ike" \ No newline at end of file diff --git a/documentation/coffee/expressions_comprehension.coffee b/documentation/coffee/expressions_comprehension.coffee new file mode 100644 index 0000000000..c608dd218a --- /dev/null +++ b/documentation/coffee/expressions_comprehension.coffee @@ -0,0 +1,3 @@ +# The first ten global properties. + +globals: (name for property, name in window)[0...10] \ No newline at end of file diff --git a/documentation/coffee/expressions_try.coffee b/documentation/coffee/expressions_try.coffee new file mode 100644 index 0000000000..3fe3a7f407 --- /dev/null +++ b/documentation/coffee/expressions_try.coffee @@ -0,0 +1,6 @@ +alert( + try + nonexistent / undefined + catch error + "The error is: " + error +) \ No newline at end of file diff --git a/documentation/coffee/functions.coffee b/documentation/coffee/functions.coffee index 35f4415aa1..eb2b9b9bc3 100644 --- a/documentation/coffee/functions.coffee +++ b/documentation/coffee/functions.coffee @@ -1,2 +1,2 @@ -square: x => x * x. -cube: x => square(x) * x. \ No newline at end of file +square: x => x * x +cube: x => square(x) * x \ No newline at end of file diff --git a/documentation/coffee/object_comprehensions.coffee b/documentation/coffee/object_comprehensions.coffee new file mode 100644 index 0000000000..8b637082b2 --- /dev/null +++ b/documentation/coffee/object_comprehensions.coffee @@ -0,0 +1,3 @@ +years_old: {max: 10, ida: 9, tim: 11} + +ages: child + " is " + age for age, child in years_old \ No newline at end of file diff --git a/documentation/coffee/objects_and_arrays.coffee b/documentation/coffee/objects_and_arrays.coffee index ff10c6ed37..f66a8a2590 100644 --- a/documentation/coffee/objects_and_arrays.coffee +++ b/documentation/coffee/objects_and_arrays.coffee @@ -1,6 +1,13 @@ song: ["do", "re", "mi", "fa", "so"] + ages: { max: 10 ida: 9 tim: 11 -} \ No newline at end of file +} + +matrix: [ + 1, 0, 1 + 0, 0, 1 + 1, 1, 0 +] \ No newline at end of file diff --git a/documentation/coffee/overview.coffee b/documentation/coffee/overview.coffee index 8e44f8aab8..295f38a132 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,8 +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) + +# Existence: +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 new file mode 100644 index 0000000000..d13a669ade --- /dev/null +++ b/documentation/coffee/range_comprehensions.coffee @@ -0,0 +1,3 @@ +for i in [0...eggs.length] by 12 + dozen_eggs: eggs[i...i+12] + deliver(new egg_carton(dozen)) diff --git a/documentation/coffee/scope.coffee b/documentation/coffee/scope.coffee index f15b3eff12..b074dad293 100644 --- a/documentation/coffee/scope.coffee +++ b/documentation/coffee/scope.coffee @@ -1,5 +1,5 @@ num: 1 change_numbers: => - num: 2 - new_num: 3. + new_num: -1 + num: 10 new_num: change_numbers() \ No newline at end of file diff --git a/documentation/coffee/splats.coffee b/documentation/coffee/splats.coffee new file mode 100644 index 0000000000..de02d2428f --- /dev/null +++ b/documentation/coffee/splats.coffee @@ -0,0 +1,25 @@ +gold: silver: the_field: "unknown" + +medalists: first, second, *rest => + gold: first + silver: second + 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(*contenders) + +alert("Gold: " + gold) +alert("Silver: " + silver) +alert("The Field: " + the_field) \ No newline at end of file diff --git a/documentation/coffee/splices.coffee b/documentation/coffee/splices.coffee new file mode 100644 index 0000000000..745237aea5 --- /dev/null +++ b/documentation/coffee/splices.coffee @@ -0,0 +1,5 @@ +numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +numbers[3..6]: [-3, -4, -5, -6] + + diff --git a/documentation/coffee/super.coffee b/documentation/coffee/super.coffee index 3e80e8045f..cc28c84d90 100644 --- a/documentation/coffee/super.coffee +++ b/documentation/coffee/super.coffee @@ -1,18 +1,18 @@ -Animal: => . +Animal: => Animal.prototype.move: meters => - alert(this.name + " moved " + meters + "m."). + alert(this.name + " moved " + meters + "m.") -Snake: name => this.name: name. +Snake: name => this.name: name Snake extends Animal Snake.prototype.move: => alert("Slithering...") - super(5). + super(5) -Horse: name => this.name: name. +Horse: name => this.name: name Horse extends Animal Horse.prototype.move: => alert("Galloping...") - super(45). + super(45) sam: new Snake("Sammy the Python") tom: new Horse("Tommy the Palomino") diff --git a/documentation/coffee/switch.coffee b/documentation/coffee/switch.coffee index 955adef6db..7d9605e610 100644 --- a/documentation/coffee/switch.coffee +++ b/documentation/coffee/switch.coffee @@ -1,9 +1,9 @@ switch day -when "Tuesday" then eat_breakfast() -when "Wednesday" then go_to_the_park() -when "Saturday" - if day is bingo_day - go_to_bingo() - go_dancing(). -when "Sunday" then go_to_church() -else go_to_work(). \ No newline at end of file + when "Tuesday" then eat_breakfast() + when "Wednesday" then go_to_the_park() + when "Saturday" + if day is bingo_day + go_to_bingo() + go_dancing() + when "Sunday" then go_to_church() + else go_to_work() \ No newline at end of file diff --git a/documentation/coffee/try.coffee b/documentation/coffee/try.coffee index 8a2c627553..169df020af 100644 --- a/documentation/coffee/try.coffee +++ b/documentation/coffee/try.coffee @@ -4,4 +4,4 @@ try catch error print(error) finally - clean_up(). \ No newline at end of file + clean_up() \ No newline at end of file diff --git a/documentation/coffee/while.coffee b/documentation/coffee/while.coffee index ab0a850a0a..3ca4a9845b 100644 --- a/documentation/coffee/while.coffee +++ b/documentation/coffee/while.coffee @@ -1,5 +1,5 @@ while demand > supply sell() - restock(). + restock() -while supply > demand then buy(). \ No newline at end of file +while supply > demand then buy() \ No newline at end of file diff --git a/documentation/index.html.erb b/documentation/index.html.erb index 8d756774c0..b7512c521a 100644 --- a/documentation/index.html.erb +++ b/documentation/index.html.erb @@ -1,3 +1,18 @@ +<%# + TODO: + Multiline and nested array comprehensions (and filters with 'when'). + Range comprehension examples (expression endpoints), with steps. + Object comprehension examples. + Significant Whitespace Rules. + Newline-delimited Matrix. + Automatic newline escaping. + All functions are named functions. + Splats in function definitions. + (Multiple) splats as arguments to a function call. + Exists? + Array assignment splice literals. +%> + <% require 'uv' def code_for(file, executable=false) @@ -49,23 +64,31 @@ preserved intact.

+

+ Latest Version: + 0.2.0 +

+

Table of Contents

Mini Overview
Installation and Usage
- Punctuation Primer
+ Significant Whitespace
Functions and Invocation
Assignment
Objects and Arrays
Lexical Scoping and Variable Safety
Conditionals, Ternaries, and Conditional Assignment
- Everything is an Expression
+ The Existence Operator
Aliases
+ Splats
While Loops
- Array Comprehensions
- Slicing Arrays with Ranges
+ Comprehensions (Arrays, Objects, and Ranges)
+ Array Slicing and Splicing with Ranges
+ Everything is an Expression
Inheritance, and Calling Super from a Subclass
+ Blocks
Embedded JavaScript
Switch/When/Else
Try/Catch/Finally
@@ -74,13 +97,22 @@ Contributing
Change Log

- +

Mini Overview

CoffeeScript on the left, compiled JavaScript output on the right.

<%= code_for('overview', 'cubed_list') %> +

+ For a longer CoffeeScript example, check out + Underscore.coffee, a port + of Underscore.js + to CoffeeScript, which, when compiled, can pass the complete Underscore test suite. + Or, clone the source and take a look in the + examples folder. +

+

Installation and Usage

@@ -113,7 +145,7 @@ gem install coffee-script -r, --run - Compile and execute the CoffeeScripts without saving the intermediate + Compile and execute scripts without saving the intermediate JavaScript. Requires Narwhal. @@ -149,7 +181,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" @@ -205,22 +237,23 @@ coffee --print app/scripts/*.coffee > concatenation.js

-

- Punctuation Primer - You don't need to use semicolons ; to terminate expressions, ending - the line will do just as well. All other whitespace is - not significant. Instead of using curly braces { } - to delimit a block of code, use a period . to mark the end of a - block, for - functions, +

+ Significant Whitespace + CoffeeScript uses Python-style significant whitespace: You don't need to + use semicolons ; to terminate expressions, ending + the line will do just as well. Semicolons can still be used to fit + multiple expressions onto a single line. Instead of using curly braces + { } to delimit blocks of code (like functions, if-statements, - switch, and try/catch. + switch, and try/catch), + use indentation.

Functions and Invocation Functions are defined by a list of parameters, an arrow, and the - function body. The empty function looks like this: =>. + function body. The empty function looks like this: =>. All + functions in CoffeeScript are named, for the benefit of debug messages.

<%= code_for('functions', 'cube(5)') %> @@ -232,8 +265,8 @@ coffee --print app/scripts/*.coffee > concatenation.js

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

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

@@ -241,7 +274,8 @@ 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. + assigning local variables, and can be moved around freely. You can mix + and match the two styles.

<%= code_for('objects_and_arrays', 'song.join(",")') %> @@ -253,25 +287,29 @@ coffee --print app/scripts/*.coffee > concatenation.js

<%= code_for('scope', 'new_num') %>

- Notice how the variables are declared with var the first time - they appear. The second reference of num, within the function, - is not redeclared because num is still in scope. As opposed - to the second occurrence of new_num, in the last line. + Notice how the all of the variable declarations have been pushed up to + the top of the closest scope, the first time they appear. + num is not redeclared within the inner function, because it's + already in scope; the new_num within the function, on the other hand, + should not be able to change the value of the external variable of the same name, and + therefore has a declaration of its own.

Although suppressed within this documentation for clarity, all 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. + 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.

Conditionals, Ternaries, and Conditional Assignment - If/else statements can be written without the use of parenthesis and - curly brackets. As with functions and other block expressions, conditionals - are closed with periods. No period is necessary when using the single-line - postfix form, with the if at the end. + If/else statements can be written without the use of parentheses and + curly brackets. As with functions and other block expressions, + multi-line conditionals are delimited by indentation. There's also a handy + postfix form, with the if or unless at the end.

CoffeeScript will compile if statements using the ternary operator @@ -279,31 +317,21 @@ coffee --print app/scripts/*.coffee > concatenation.js

<%= code_for('conditionals') %>

- The conditional assignment operators are available: ||=, + The conditional assignment operators are included: ||=, which only assigns a value to a variable if the variable's current value is falsy, and &&=, which only replaces the value of truthy variables.

-

- Everything is an Expression (at least, as much as possible) - You might have noticed how even though we don't add return statements - to CoffeeScript functions, they nonetheless return their final value. - The CoffeeScript compiler tries to make sure that all statements in the - language can be used as expressions. Watch how the return gets - pushed down into each possible branch of execution, in the function - below. +

+ The Existence 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 existence operator ? returns true unless + a variable is null or undefined, which makes it analogous + to Ruby's nil?

- <%= code_for('expressions', 'eldest') %> -

- The same mechanism is used to push down assignment through switch - statements, and if-elses (although the ternary operator is preferred). - Another part of manipulating assignment statements is - CoffeeScript's declaration of new variables at the top of the - current scope. This allows assignment to be used as a piece of an - expression. -

- <%= code_for('expressions_assignment', 'six') %> + <%= code_for('existence') %>

Aliases @@ -335,6 +363,15 @@ coffee --print app/scripts/*.coffee > concatenation.js

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

+ Splats + 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. +

+ <%= code_for('splats', true) %> +

While Loops The only low-level loop that CoffeeScript provides is the while loop. @@ -347,8 +384,8 @@ coffee --print app/scripts/*.coffee > concatenation.js each (forEach) style iterators, or...

-

- Array Comprehensions +

+ Comprehensions (Arrays, Objects, and Ranges) For your looping needs, CoffeeScript provides array comprehensions similar to Python's. They replace (and compile into) for loops, with optional guard clauses and the value of the current array index. @@ -358,13 +395,19 @@ coffee --print app/scripts/*.coffee > concatenation.js

<%= code_for('array_comprehensions') %>

- If you're not iterating over an actual array, you can use a range to - specify the start and end of an array comprehension: - coundown(i) for i in [10..1]. + If you know the start and end of your loop, or would like to step through + in fixed-size increments, you can use a range to specify the start and + end of your comprehension: +

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

+ Comprehensions can also be used to iterate over the values and keys in + an object:

+ <%= code_for('object_comprehensions', 'ages.join(", ")') %> -

- Slicing Arrays with Ranges +

+ Array Slicing and Splicing with Ranges CoffeeScript borrows Ruby's range syntax for extracting slices of arrays. With two dots (3..5), the range @@ -373,6 +416,39 @@ coffee --print app/scripts/*.coffee > concatenation.js a range that excludes the end.

<%= code_for('slices', 'numbers_copy') %> +

+ The same syntax can be used with assignment to replace a segment of an + array with new values (to splice it). +

+ <%= code_for('splices', 'numbers') %> + +

+ Everything is an Expression (at least, as much as possible) + You might have noticed how even though we don't add return statements + to CoffeeScript functions, they nonetheless return their final value. + The CoffeeScript compiler tries to make sure that all statements in the + language can be used as expressions. Watch how the return gets + pushed down into each possible branch of execution, in the function + below. +

+ <%= code_for('expressions', 'eldest') %> +

+ Because variable declarations occur at the top of scope, assignment can + be used within expressions, even for variables that haven't been seen before: +

+ <%= code_for('expressions_assignment', 'six') %> +

+ Things that would otherwise be statements in JavaScript, when used + as part of an expression in CoffeeScript, are converted into expressions + by wrapping them in a closure. This lets you do useful things, like assign + the result of a comprehension to a variable: +

+ <%= code_for('expressions_comprehension', 'globals') %> +

+ As well as silly things, like passing a try/catch statement directly + into a function call: +

+ <%= code_for('expressions_try', true) %>

Inheritance, and Calling Super from a Subclass @@ -393,6 +469,15 @@ 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') %> +

Embedded JavaScript If you ever need to interpolate literal JavaScript snippets, you can @@ -419,18 +504,32 @@ coffee --print app/scripts/*.coffee > concatenation.js

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

+

Multiline Strings Multiline strings are allowed in CoffeeScript.

<%= code_for('strings', 'moby_dick') %> - +

Resources

- -

- Source Code
- Bugs and Feature Requests
-

+ +

Contributing

@@ -441,13 +540,13 @@ coffee --print app/scripts/*.coffee > concatenation.js

Change Log

- + +

+ 0.2.0 + Major release. Significant whitespace. Better statement-to-expression + conversion. Splats. Splice literals. Object comprehensions. Blocks. + The existence operator. Many thanks to all the folks who posted issues, + with special thanks to + Liam O'Connor-Davis for whitespace + and expression help. +

+

0.1.6 Bugfix for running coffee --interactive and --run - from outside of the CoffeeScript directory. Bugfix for nested - function/if-statements. + from outside of the CoffeeScript directory. Bugfix for nested + function/if-statements.

- +

0.1.5 Array slice literals and array comprehensions can now both take Ruby-style - ranges to specify the start and end. JavaScript variable declaration is - now pushed up to the top of the scope, making all assignment statements into + ranges to specify the start and end. JavaScript variable declaration is + now pushed up to the top of the scope, making all assignment statements into expressions. You can use \ to escape newlines. The coffee-script command is now called coffee.

diff --git a/documentation/js/array_comprehensions.js b/documentation/js/array_comprehensions.js index 636ccb49db..089b9fcf35 100644 --- a/documentation/js/array_comprehensions.js +++ b/documentation/js/array_comprehensions.js @@ -1,20 +1,34 @@ (function(){ - var __a, __b, __c, __d, __e, __f, __g, __h, food, i, lunch, row; + var __a, __b, __c, __d, __e, __f, __g, __h, __i, __j, food, lunch, roid, roid2; // Eat lunch. - __a = ['toast', 'cheese', 'wine']; - __d = []; - for (__b=0, __c=__a.length; __b<__c; __b++) { - food = __a[__b]; - __d[__b] = food.eat(); + lunch = (function() { + __a = ['toast', 'cheese', 'wine']; + __c = []; + for (__b in __a) { + if (__a.hasOwnProperty(__b)) { + food = __a[__b]; + __d = eat(food); + __c.push(__d); + } + } + return __c; + })(); + // Naive collision detection. + __e = asteroids; + for (__f in __e) { + if (__e.hasOwnProperty(__f)) { + roid = __e[__f]; + __h = asteroids; + for (__i in __h) { + if (__h.hasOwnProperty(__i)) { + roid2 = __h[__i]; + if (roid !== roid2) { + if (roid.overlaps(roid2)) { + roid.explode(); + } + } + } + } + } } - lunch = __d; - // Zebra-stripe a table. - __e = table; - __h = []; - for (__f=0, __g=__e.length; __f<__g; __f++) { - row = __e[__f]; - i = __f; - __h[__f] = i % 2 === 0 ? highlight(row) : null; - } - __h; })(); \ No newline at end of file diff --git a/documentation/js/blocks.js b/documentation/js/blocks.js new file mode 100644 index 0000000000..f95dd31b45 --- /dev/null +++ b/documentation/js/blocks.js @@ -0,0 +1,8 @@ +(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/existence.js b/documentation/js/existence.js new file mode 100644 index 0000000000..aa58531626 --- /dev/null +++ b/documentation/js/existence.js @@ -0,0 +1,6 @@ +(function(){ + var solipsism; + if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) { + solipsism = true; + } +})(); \ No newline at end of file diff --git a/documentation/js/expressions.js b/documentation/js/expressions.js index 78f9244cba..eb2e983b0d 100644 --- a/documentation/js/expressions.js +++ b/documentation/js/expressions.js @@ -1,6 +1,6 @@ (function(){ var eldest, grade; - grade = function(student) { + grade = function grade(student) { if (student.excellent_work) { return "A+"; } else if (student.okay_stuff) { diff --git a/documentation/js/expressions_comprehension.js b/documentation/js/expressions_comprehension.js new file mode 100644 index 0000000000..5dea5cf044 --- /dev/null +++ b/documentation/js/expressions_comprehension.js @@ -0,0 +1,16 @@ +(function(){ + var __a, __b, __c, globals, name, property; + // The first ten global properties. + globals = ((function() { + __a = window; + __b = []; + for (name in __a) { + if (__a.hasOwnProperty(name)) { + property = __a[name]; + __c = name; + __b.push(__c); + } + } + return __b; + })()).slice(0, 10); +})(); \ No newline at end of file diff --git a/documentation/js/expressions_try.js b/documentation/js/expressions_try.js new file mode 100644 index 0000000000..9c236f65e8 --- /dev/null +++ b/documentation/js/expressions_try.js @@ -0,0 +1,9 @@ +(function(){ + alert((function() { + try { + return nonexistent / undefined; + } catch (error) { + return "The error is: " + error; + } + })()); +})(); \ No newline at end of file diff --git a/documentation/js/functions.js b/documentation/js/functions.js index d77c2c2695..80c1734413 100644 --- a/documentation/js/functions.js +++ b/documentation/js/functions.js @@ -1,9 +1,9 @@ (function(){ var cube, square; - square = function(x) { + square = function square(x) { return x * x; }; - cube = function(x) { + cube = function cube(x) { return square(x) * x; }; })(); \ No newline at end of file diff --git a/documentation/js/object_comprehensions.js b/documentation/js/object_comprehensions.js new file mode 100644 index 0000000000..757ad863c6 --- /dev/null +++ b/documentation/js/object_comprehensions.js @@ -0,0 +1,20 @@ +(function(){ + var __a, __b, __c, age, ages, child, years_old; + years_old = { + max: 10, + ida: 9, + tim: 11 + }; + ages = (function() { + __a = years_old; + __b = []; + for (child in __a) { + if (__a.hasOwnProperty(child)) { + age = __a[child]; + __c = child + " is " + age; + __b.push(__c); + } + } + return __b; + })(); +})(); \ No newline at end of file diff --git a/documentation/js/objects_and_arrays.js b/documentation/js/objects_and_arrays.js index cfd1011ed6..3c7de98f03 100644 --- a/documentation/js/objects_and_arrays.js +++ b/documentation/js/objects_and_arrays.js @@ -1,9 +1,10 @@ (function(){ - var ages, song; + var ages, matrix, song; song = ["do", "re", "mi", "fa", "so"]; ages = { max: 10, ida: 9, tim: 11 }; + matrix = [1, 0, 1, 0, 0, 1, 1, 1, 0]; })(); \ No newline at end of file diff --git a/documentation/js/overview.js b/documentation/js/overview.js index 32cc4b3413..e3832187ee 100644 --- a/documentation/js/overview.js +++ b/documentation/js/overview.js @@ -1,5 +1,5 @@ (function(){ - var __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, square; + var __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, race, square; // Assignment: number = 42; opposite_day = true; @@ -8,7 +8,7 @@ number = -42; } // Functions: - square = function(x) { + square = function square(x) { return x * x; }; // Arrays: @@ -17,16 +17,31 @@ math = { root: Math.sqrt, square: square, - cube: function(x) { + cube: function cube(x) { return x * square(x); } }; - // Array comprehensions: - __a = list; - __d = []; - for (__b=0, __c=__a.length; __b<__c; __b++) { - num = __a[__b]; - __d[__b] = math.cube(num); + // Splats: + race = function race(winner) { + var runners; + runners = Array.prototype.slice.call(arguments, 1); + return print(winner, runners); + }; + // Existence: + if ((typeof elvis !== "undefined" && elvis !== null)) { + alert("I knew it!"); } - cubed_list = __d; + // Array comprehensions: + cubed_list = (function() { + __a = list; + __c = []; + for (__b in __a) { + if (__a.hasOwnProperty(__b)) { + num = __a[__b]; + __d = math.cube(num); + __c.push(__d); + } + } + return __c; + })(); })(); \ No newline at end of file diff --git a/documentation/js/range_comprehensions.js b/documentation/js/range_comprehensions.js new file mode 100644 index 0000000000..7457b7f4a8 --- /dev/null +++ b/documentation/js/range_comprehensions.js @@ -0,0 +1,9 @@ +(function(){ + var __a, __b, __c, __d, __e, dozen_eggs, i; + __d = 0; + __e = eggs.length; + for (__c=0, i=__d; (__d <= __e ? i < __e : i > __e); (__d <= __e ? i += 12 : i -= 12), __c++) { + dozen_eggs = eggs.slice(i, i + 12); + deliver(new egg_carton(dozen)); + } +})(); \ No newline at end of file diff --git a/documentation/js/scope.js b/documentation/js/scope.js index f4f1b4d289..3319f50c45 100644 --- a/documentation/js/scope.js +++ b/documentation/js/scope.js @@ -1,10 +1,10 @@ (function(){ var change_numbers, new_num, num; num = 1; - change_numbers = function() { + change_numbers = function change_numbers() { var new_num; - num = 2; - return (new_num = 3); + new_num = -1; + return num = 10; }; new_num = change_numbers(); })(); \ No newline at end of file diff --git a/documentation/js/splats.js b/documentation/js/splats.js new file mode 100644 index 0000000000..31f25a791d --- /dev/null +++ b/documentation/js/splats.js @@ -0,0 +1,16 @@ +(function(){ + var contenders, gold, medalists, silver, the_field; + gold = silver = the_field = "unknown"; + medalists = function medalists(first, second) { + var rest; + rest = Array.prototype.slice.call(arguments, 2); + gold = first; + silver = second; + 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); + alert("Gold: " + gold); + alert("Silver: " + silver); + alert("The Field: " + the_field); +})(); \ No newline at end of file diff --git a/documentation/js/splices.js b/documentation/js/splices.js new file mode 100644 index 0000000000..0192c5e5e8 --- /dev/null +++ b/documentation/js/splices.js @@ -0,0 +1,5 @@ +(function(){ + var numbers; + numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6])); +})(); \ No newline at end of file diff --git a/documentation/js/super.js b/documentation/js/super.js index 252d06127f..ce26399ee7 100644 --- a/documentation/js/super.js +++ b/documentation/js/super.js @@ -1,27 +1,27 @@ (function(){ var Animal, Horse, Snake, sam, tom; - Animal = function() { + Animal = function Animal() { }; - Animal.prototype.move = function(meters) { + Animal.prototype.move = function move(meters) { return alert(this.name + " moved " + meters + "m."); }; - Snake = function(name) { - return (this.name = name); + Snake = function Snake(name) { + return this.name = name; }; Snake.__superClass__ = Animal.prototype; Snake.prototype = new Animal(); Snake.prototype.constructor = Snake; - Snake.prototype.move = function() { + Snake.prototype.move = function move() { alert("Slithering..."); return Snake.__superClass__.move.call(this, 5); }; - Horse = function(name) { - return (this.name = name); + Horse = function Horse(name) { + return this.name = name; }; Horse.__superClass__ = Animal.prototype; Horse.prototype = new Animal(); Horse.prototype.constructor = Horse; - Horse.prototype.move = function() { + Horse.prototype.move = function move() { alert("Galloping..."); return Horse.__superClass__.move.call(this, 45); }; diff --git a/documentation/underscore.html b/documentation/underscore.html new file mode 100644 index 0000000000..b502cf222b --- /dev/null +++ b/documentation/underscore.html @@ -0,0 +1,616 @@ + + + + + + + Underscore.coffee + + + + + +
   1 
+   2    # Underscore.coffee
+   3    # (c) 2009 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.
+   7    # For all details and documentation:
+   8    # http://documentcloud.github.com/underscore/
+   9 
+  10 
+  11    # ------------------------- Baseline setup ---------------------------------
+  12 
+  13    # Establish the root object, "window" in the browser, or "global" on the server.
+  14    root: this
+  15 
+  16 
+  17    # Save the previous value of the "_" variable.
+  18    previousUnderscore: root._
+  19 
+  20 
+  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 =>
+  25      this._wrapped: obj
+  26      this
+  27 
+  28 
+  29    # Establish the object that gets thrown to break out of a loop iteration.
+  30    breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
+  31 
+  32 
+  33    # Create a safe reference to the Underscore object for reference below.
+  34    _: root._: obj => new wrapper(obj)
+  35 
+  36 
+  37    # Export the Underscore object for CommonJS.
+  38    if typeof(exports) != 'undefined' then exports._: _
+  39 
+  40 
+  41    # Create quick reference variables for speed access to core prototypes.
+  42    slice:                Array.prototype.slice
+  43    unshift:              Array.prototype.unshift
+  44    toString:             Object.prototype.toString
+  45    hasOwnProperty:       Object.prototype.hasOwnProperty
+  46    propertyIsEnumerable: Object.prototype.propertyIsEnumerable
+  47 
+  48 
+  49    # Current version.
+  50    _.VERSION: '0.5.3'
+  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 =>
+  58      index: 0
+  59      try
+  60        return obj.forEach(iterator, context) if obj.forEach
+  61        if _.isArray(obj) or _.isArguments(obj)
+  62          return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
+  63        iterator.call(context, val, key, obj) for val, key in obj
+  64      catch e
+  65        throw e if e isnt breaker
+  66      obj
+  67 
+  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 =>
+  72      return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
+  73      results: []
+  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 =>
+  82      return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
+  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 =>
+  91      return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
+  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 =>
+  99      result: null
+ 100      _.each(obj) value, index, list =>
+ 101        if iterator.call(context, value, index, list)
+ 102          result: value
+ 103          _.breakLoop()
+ 104      result
+ 105 
+ 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 =>
+ 110      if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context)
+ 111      results: []
+ 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 =>
+ 119      results: []
+ 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 =>
+ 128      iterator ||= _.identity
+ 129      return obj.every(iterator, context) if obj and _.isFunction(obj.every)
+ 130      result: true
+ 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 =>
+ 139      iterator ||= _.identity
+ 140      return obj.some(iterator, context) if obj and _.isFunction(obj.some)
+ 141      result: false
+ 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 =>
+ 150      return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
+ 151      for val in obj
+ 152        return true if val is target
+ 153      false
+ 154 
+ 155 
+ 156    # Invoke a method with arguments on every item in a collection.
+ 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]))
+ 165 
+ 166 
+ 167    # Return the maximum item or (item-based computation).
+ 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 =>
+ 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 =>
+ 179      return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
+ 180      result: {computed: Infinity}
+ 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 =>
+ 190        {value: value, criteria: iterator.call(context, value, index, list)}
+ 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')
+ 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 =>
+ 200      iterator ||= _.identity
+ 201      low: 0; high: array.length
+ 202      while low < high
+ 203        mid: (low + high) >> 1
+ 204        if iterator(array[mid]) < iterator(obj) then low: mid + 1 else high: mid
+ 205      low
+ 206 
+ 207 
+ 208    # Convert anything iterable into a real, live array.
+ 209    _.toArray: iterable =>
+ 210      return []                   if (!iterable)
+ 211      return iterable.toArray()   if (iterable.toArray)
+ 212      return iterable             if (_.isArray(iterable))
+ 213      return slice.call(iterable) if (_.isArguments(iterable))
+ 214      _.values(iterable)
+ 215 
+ 216 
+ 217    # Return the number of elements in an object.
+ 218    _.size: obj => _.toArray(obj).length
+ 219 
+ 220 
+ 221    # -------------------------- Array Functions: ------------------------------
+ 222 
+ 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 =>
+ 227      if n and not guard then slice.call(array, 0, n) else array[0]
+ 228 
+ 229 
+ 230    # Returns everything but the first entry of the array. Aliased as "tail".
+ 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 =>
+ 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]
+ 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]
+ 244 
+ 245 
+ 246    # Return a completely flattened version of an array.
+ 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 =>
+ 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 =>
+ 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))
+ 266      memo
+ 267 
+ 268 
+ 269    # Produce an array that contains every item shared between all the
+ 270    # passed-in arrays.
+ 271    _.intersect: array =>
+ 272      rest: _.rest(arguments)
+ 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
+ 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
+ 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
+ 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
+ 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)))
+ 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
+ 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)
+ 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)))
+ 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)))
+ 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]
+ 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 val, key in obj
+ 384 
+ 385 
+ 386    # Retrieve the values of an object's properties.
+ 387    _.values: obj =>
+ 388      _.map(obj, _.identity)
+ 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()
+ 394 
+ 395 
+ 396    # Extend a given object with all of the properties in a source object.
+ 397    _.extend: destination, source =>
+ 398      for val, key in source
+ 399        destination[key]: val
+ 400      destination
+ 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)
+ 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
+ 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
+ 450 
+ 451 
+ 452    # Is a given array or object empty?
+ 453    _.isEmpty:      obj => _.keys(obj).length is 0
+ 454 
+ 455 
+ 456    # Is a given value a DOM element?
+ 457    _.isElement:    obj => obj and obj.nodeType is 1
+ 458 
+ 459 
+ 460    # Is a given value an array?
+ 461    _.isArray:      obj => !!(obj and obj.concat and obj.unshift)
+ 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')
+ 466 
+ 467 
+ 468    # Is the given value a function?
+ 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))
+ 474 
+ 475 
+ 476    # Is a given value a number?
+ 477    _.isNumber:     obj => 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)
+ 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))
+ 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)
+ 491 
+ 492 
+ 493    # Is a given value equal to null?
+ 494    _.isNull:       obj => obj is null
+ 495 
+ 496 
+ 497    # Is a given variable 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: =>
+ 506      root._: previousUnderscore
+ 507      this
+ 508 
+ 509 
+ 510    # Keep the identity function around for default iterators.
+ 511    _.identity: value => value
+ 512 
+ 513 
+ 514    # Break out of the middle of an iteration.
+ 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 =>
+ 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
+ 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        unshift.call(arguments, this._wrapped)
+ 568        result(method.apply(_, arguments), this._chain)
+ 569 
+ 570 
+ 571    # Add all mutator Array functions to the wrapper.
+ 572    _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift']) name =>
+ 573      method: Array.prototype[name]
+ 574      wrapper.prototype[name]: =>
+ 575        method.apply(this._wrapped, arguments)
+ 576        result(this._wrapped, this._chain)
+ 577 
+ 578 
+ 579    # Add all accessor Array functions to the wrapper.
+ 580    _.each(['concat', 'join', 'slice']) name =>
+ 581      method: Array.prototype[name]
+ 582      wrapper.prototype[name]: =>
+ 583        result(method.apply(this._wrapped, arguments), this._chain)
+ 584 
+ 585 
+ 586    # Start chaining a wrapped Underscore object.
+ 587    wrapper.prototype.chain: =>
+ 588      this._chain: true
+ 589      this
+ 590 
+ 591 
+ 592    # Extracts the result from a wrapped and chained object.
+ 593    wrapper.prototype.value: => this._wrapped
+
+ + diff --git a/examples/code.coffee b/examples/code.coffee index 23458fd834..ca78218c55 100644 --- a/examples/code.coffee +++ b/examples/code.coffee @@ -1,16 +1,16 @@ # 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 is 0 -even: x => x % 2 isnt 0. +even: x => x % 2 isnt 0 run_loop: => - fire_events( e => e.stopPropagation(). ) + fire_events(e => e.stopPropagation()) listen() - wait(). + wait() # Objects: dense_object_literal: {one: 1, two: 2, three: 3} @@ -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}] +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: [] @@ -45,9 +45,9 @@ if submarine.shields_up else if submarine.sinking abandon_ship() else - run_away(). + run_away() -eldest: if 25 > 21 then liz else marge. +eldest: if 25 > 21 then liz else marge decoration: medal_of_honor if war_hero @@ -58,8 +58,8 @@ race: => run() walk() crawl() - if tired then return sleep(). - race(). + if tired then return sleep() + race() # Conditional assignment: good ||= evil @@ -81,54 +81,54 @@ try dogs_and_cats_living_together() throw "up" catch error - print( error ) + print(error) finally - clean_up(). + clean_up() -try all_hell_breaks_loose() catch error print(error) finally clean_up(). +try all_hell_breaks_loose() catch error then print(error) finally clean_up() # While loops, break and continue. while demand > supply sell() - restock(). + restock() -while supply > demand then buy(). +while supply > demand then buy() while true break if broken - continue if continuing. + continue if continuing # Unary operators. !!true # Lexical scoping. -a: 5 +v_1: 5 change_a_and_set_b: => - a: 10 - b: 15. -b: 20 + v_1: 10 + v_2: 15 +v_2: 20 # Array comprehensions. -supper: food.capitalize() for food in ['toast', 'cheese', 'wine']. +supper: food.capitalize() for food in ['toast', 'cheese', 'wine'] -drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] if even(i). +drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] when even(i) # Switch statements ("else" serves as a default). activity: switch day -when "Tuesday" then eat_breakfast() -when "Sunday" then go_to_church() -when "Saturday" then go_to_the_park() -when "Wednesday" - if day is bingo_day - go_to_bingo() - else - eat_breakfast() - go_to_work() - eat_dinner(). -else go_to_work(). + when "Tuesday" then eat_breakfast() + when "Sunday" then go_to_church() + when "Saturday" then go_to_the_park() + when "Wednesday" + if day is bingo_day + go_to_bingo() + else + eat_breakfast() + go_to_work() + eat_dinner() + 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,21 +140,21 @@ sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad." # Inheritance and calling super. -Animal: => . +Animal: => Animal.prototype.move: meters => - alert(this.name + " moved " + meters + "m."). + alert(this.name + " moved " + meters + "m.") -Snake: name => this.name: name. +Snake: name => this.name: name Snake extends Animal Snake.prototype.move: => alert('Slithering...') - super(5). + super(5) -Horse: name => this.name: name. +Horse: name => this.name: name Horse extends Animal Horse.prototype.move: => alert('Galloping...') - super(45). + super(45) sam: new Snake("Sammy the Snake") tom: new Horse("Tommy the Horse") diff --git a/examples/documents.coffee b/examples/documents.coffee index 1908a88bc4..439dd4ca56 100644 --- a/examples/documents.coffee +++ b/examples/documents.coffee @@ -1,7 +1,7 @@ # Document Model dc.model.Document: dc.Model.extend({ - constructor: attributes => this.base(attributes). + constructor: attributes => this.base(attributes) # For display, show either the highlighted search results, or the summary, # if no highlights are available. @@ -9,22 +9,22 @@ dc.model.Document: dc.Model.extend({ # 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, ' '). + 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.).). + _.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). + Bookmarks.create(bookmark) # Inspect. - toString: => 'Document ' + this.id + ' "' + this.get('title') + '"'. + toString: => 'Document ' + this.id + ' "' + this.get('title') + '"' }) @@ -37,31 +37,31 @@ dc.model.DocumentSet: dc.model.RESTfulSet.extend({ constructor: options => this.base(options) - _.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText'). + _.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText') - selected: => _.select(this.models(), m => m.get('selected').). + selected: => _.select(this.models(), m => m.get('selected')) - selectedIds: => _.pluck(this.selected(), 'id'). + selectedIds: => _.pluck(this.selected(), 'id') - countSelected: => this.selected().length. + countSelected: => this.selected().length downloadSelectedViewers: => - dc.app.download('/download/' + this.selectedIds().join('/') + '/document_viewer.zip'). + 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'). + 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'). + 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 == dc.Model.CHANGED and model.hasChanged('selected') - if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this)).. + if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this)) }) diff --git a/examples/poignant.coffee b/examples/poignant.coffee index 973248ce29..9714c980a3 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,10 @@ # 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 } @@ -33,8 +33,8 @@ LotteryTicket: { WishScanner: { scan_for_a_wish: => - wish: this.read().detect( thought => thought.index('wish: ') is 0. ) - wish.replace('wish: ', ''). + wish: this.read().detect(thought => thought.index('wish: ') is 0) + wish.replace('wish: ', '') } @@ -79,28 +79,28 @@ Creature : { # This method applies a hit taken during a fight. hit: damage => - p_up: Math.rand( this.charisma ) + p_up: Math.rand(this.charisma) if p_up % 9 is 7 this.life += p_up / 4 - puts( "[" + this.name + " magick powers up " + p_up + "!]" ). + puts("[" + this.name + " magick powers up " + p_up + "!]") this.life -= damage - if this.life <= 0 then puts( "[" + this.name + " has died.]" ).. + if this.life <= 0 then puts("[" + this.name + " has died.]") # This method takes one turn in a fight. fight: enemy, weapon => - if this.life <= 0 then return puts( "[" + this.name + "is too dead to fight!]" ). + if this.life <= 0 then return puts("[" + this.name + "is too dead to fight!]") # Attack the opponent. - your_hit: Math.rand( this.strength + weapon ) - puts( "[You hit with " + your_hit + "points of damage!]" ) - enemy.hit( your_hit ) + your_hit: Math.rand(this.strength + weapon) + puts("[You hit with " + your_hit + "points of damage!]") + enemy.hit(your_hit) # Retaliation. - puts( enemy ) + puts(enemy) if enemy.life > 0 - enemy_hit: Math.rand( enemy.strength + enemy.weapon ) - puts( "[Your enemy hit with " + enemy_hit + "points of damage!]" ) - this.hit( enemy_hit ).. + enemy_hit: Math.rand(enemy.strength + enemy.weapon) + puts("[Your enemy hit with " + enemy_hit + "points of damage!]") + this.hit(enemy_hit) } @@ -123,12 +123,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)) @@ -149,5 +149,5 @@ wipe_mutterings_from: sentence => while sentence.indexOf('(') >= 0 open: sentence.indexOf('(') - 1 close: sentence.indexOf(')') + 1 - sentence: sentence[0..open] + sentence[close..sentence.length]. - sentence. \ No newline at end of file + sentence: sentence[0..open] + sentence[close..sentence.length] + sentence \ No newline at end of file diff --git a/examples/underscore.coffee b/examples/underscore.coffee index 8c463fcd32..71e56d0362 100644 --- a/examples/underscore.coffee +++ b/examples/underscore.coffee @@ -1,107 +1,126 @@ -# Underscore.js -# (c) 2009 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. -# For all details and documentation: -# http://documentcloud.github.com/underscore/ - -# ------------------------- Baseline setup --------------------------------- - -# Establish the root object, "window" in the browser, or "global" on the server. -root: this - -# Save the previous value of the "_" variable. -previousUnderscore: root._ - -# 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 => this._wrapped: obj. - -# Establish the object that gets thrown to break out of a loop iteration. -breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration. - -# Create a safe reference to the Underscore object for reference below. -_: root._: obj => new wrapper(obj). - -# Export the Underscore object for CommonJS. -if typeof(exports) != 'undefined' then exports._: _. - -# Create quick reference variables for speed access to core prototypes. -slice: Array.prototype.slice -unshift: Array.prototype.unshift -toString: Object.prototype.toString -hasOwnProperty: Object.prototype.hasOwnProperty -propertyIsEnumerable: Object.prototype.propertyIsEnumerable - -# Current version. -_.VERSION: '0.5.1' - -# ------------------------ Collection Functions: --------------------------- - -# The cornerstone, an each implementation. -# Handles objects implementing forEach, arrays, and raw objects. -_.each: obj, iterator, context => - index: 0 - try - return obj.forEach(iterator, context) if obj.forEach - return iterator.call(context, item, i, obj) for item, i in obj. if _.isArray(obj) or _.isArguments(obj) - iterator.call(context, obj[key], key, obj) for key in _.keys(obj). - catch e - throw e if e isnt breaker. - obj. - -# Return the results of applying the iterator to each element. Use JavaScript -# 1.6's version of map, if possible. -_.map: obj, iterator, context => - return obj.map(iterator, context) if (obj and _.isFunction(obj.map)) - results: [] - mapper: value, index, list => results.push(iterator.call(context, value, index, list)). - _.each(obj, mapper) - 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 => - return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce)) - reducer: value, index, list => memo: iterator.call(context, memo, value, index, list). - _.each(obj, reducer) - 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 => - return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight)) - reversed: _.clone(_.toArray(obj)).reverse() - reverser: value, index => memo: iterator.call(context, memo, value, index, obj). - _.each(reversed, reverser) - memo. + + # Underscore.coffee + # (c) 2009 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. + # For all details and documentation: + # http://documentcloud.github.com/underscore/ + + + # ------------------------- Baseline setup --------------------------------- + + # Establish the root object, "window" in the browser, or "global" on the server. + root: this + + + # Save the previous value of the "_" variable. + previousUnderscore: root._ + + + # 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 => + this._wrapped: obj + this + + + # Establish the object that gets thrown to break out of a loop iteration. + breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration + + + # Create a safe reference to the Underscore object for reference below. + _: root._: obj => new wrapper(obj) + + + # Export the Underscore object for CommonJS. + if typeof(exports) != 'undefined' then exports._: _ + + + # Create quick reference variables for speed access to core prototypes. + slice: Array.prototype.slice + unshift: Array.prototype.unshift + toString: Object.prototype.toString + hasOwnProperty: Object.prototype.hasOwnProperty + propertyIsEnumerable: Object.prototype.propertyIsEnumerable + + + # Current version. + _.VERSION: '0.5.3' + + + # ------------------------ Collection Functions: --------------------------- + + # The cornerstone, an each implementation. + # Handles objects implementing forEach, arrays, and raw objects. + _.each: obj, iterator, context => + index: 0 + try + return obj.forEach(iterator, context) if obj.forEach + if _.isArray(obj) or _.isArguments(obj) + return iterator.call(context, obj[i], i, obj) for i in [0...obj.length] + iterator.call(context, val, key, obj) for val, key in obj + catch e + throw e if e isnt breaker + obj + + + # Return the results of applying the iterator to each element. Use JavaScript + # 1.6's version of map, if possible. + _.map: obj, iterator, context => + return obj.map(iterator, context) if (obj and _.isFunction(obj.map)) + results: [] + _.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 => + return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce)) + _.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 => + return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight)) + _.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 => result: null - _.each(obj, (value, index, list => + _.each(obj) value, index, list => if iterator.call(context, value, index, list) result: value - _.breakLoop()..)) - result. + _.breakLoop() + result + # Return all the elements that pass a truth test. Use JavaScript 1.6's # filter(), if it exists. _.select: obj, iterator, context => - if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context). + if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context) results: [] - _.each(obj, (value, index, list => - results.push(value) if iterator.call(context, value, index, list).)) - results. + _.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 => results: [] - _.each(obj, (value, index, list => - results.push(value) if not iterator.call(context, value, index, list).)) - results. + _.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. @@ -109,9 +128,10 @@ _.reduceRight: obj, memo, iterator, context => iterator ||= _.identity return obj.every(iterator, context) if obj and _.isFunction(obj.every) result: true - _.each(obj, (value, index, list => - _.breakLoop() unless result: result and iterator.call(context, value, index, list).)) - result. + _.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. @@ -119,193 +139,193 @@ _.reduceRight: obj, memo, iterator, context => iterator ||= _.identity return obj.some(iterator, context) if obj and _.isFunction(obj.some) result: false - _.each(obj, (value, index, list => - _.breakLoop() if (result: iterator.call(context, value, index, list)).)) - result. + _.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 => return _.indexOf(obj, target) isnt -1 if _.isArray(obj) - found: false - _.each(obj, (value => - _.breakLoop() if (found: value is target).)) - found. + for val in obj + return true if val is target + false + # Invoke a method with arguments on every item in a collection. _.invoke: obj, method => args: _.rest(arguments, 2) - _.map(obj, (value => - (if method then value[method] else value.).apply(value, args).)). + (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, (value => value[key].)). + _.map(obj, (val => val[key])) + # Return the maximum item or (item-based computation). _.max: obj, iterator, context => - return Math.max.apply(Math, obj) if !iterator and _.isArray(obj) + return Math.max.apply(Math, obj) if not iterator and _.isArray(obj) result: {computed: -Infinity} - _.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 = function(obj, iterator, context) { -# if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); -# var result = {computed : Infinity}; -# _.each(obj, function(value, index, list) { -# var computed = iterator ? iterator.call(context, value, index, list) : value; -# computed < result.computed && (result = {value : value, computed : computed}); -# }); -# return result.value; -# }; -# -# # Sort the object's values by a criteria produced by an iterator. -# _.sortBy = function(obj, iterator, context) { -# return _.pluck(_.map(obj, function(value, index, list) { -# return { -# value : value, -# criteria : iterator.call(context, value, index, list) -# }; -# }).sort(function(left, right) { -# var a = left.criteria, b = right.criteria; -# return a < b ? -1 : a > b ? 1 : 0; -# }), '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 = function(array, obj, iterator) { -# iterator = iterator || _.identity; -# var low = 0, high = array.length; -# while (low < high) { -# var mid = (low + high) >> 1; -# iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; -# } -# return low; -# }; -# -# # Convert anything iterable into a real, live array. -# _.toArray = function(iterable) { -# if (!iterable) return []; -# if (iterable.toArray) return iterable.toArray(); -# if (_.isArray(iterable)) return iterable; -# if (_.isArguments(iterable)) return slice.call(iterable); -# return _.map(iterable, function(val){ return val; }); -# }; -# -# # Return the number of elements in an object. -# _.size = function(obj) { -# return _.toArray(obj).length; -# }; -# -# /*-------------------------- Array Functions: ------------------------------*/ -# -# # 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 = function(array, n, guard) { -# return n && !guard ? slice.call(array, 0, n) : array[0]; -# }; -# -# # Returns everything but the first entry of the array. Aliased as "tail". -# # 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 = function(array, index, guard) { -# return slice.call(array, _.isUndefined(index) || guard ? 1 : index); -# }; -# -# # Get the last element of an array. -# _.last = function(array) { -# return array[array.length - 1]; -# }; -# -# # Trim out all falsy values from an array. -# _.compact = function(array) { -# return _.select(array, function(value){ return !!value; }); -# }; -# -# # Return a completely flattened version of an array. -# _.flatten = function(array) { -# return _.reduce(array, [], function(memo, value) { -# if (_.isArray(value)) return memo.concat(_.flatten(value)); -# memo.push(value); -# return memo; -# }); -# }; -# -# # Return a version of the array that does not contain the specified value(s). -# _.without = function(array) { -# var values = _.rest(arguments); -# return _.select(array, function(value){ return !_.include(values, value); }); -# }; -# -# # 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 = function(array, isSorted) { -# return _.reduce(array, [], function(memo, el, i) { -# if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el); -# return memo; -# }); -# }; -# -# # Produce an array that contains every item shared between all the -# # passed-in arrays. -# _.intersect = function(array) { -# var rest = _.rest(arguments); -# return _.select(_.uniq(array), function(item) { -# return _.all(rest, function(other) { -# return _.indexOf(other, item) >= 0; -# }); -# }); -# }; -# -# # Zip together multiple lists into a single array -- elements that share -# # an index go together. -# _.zip = function() { -# var args = _.toArray(arguments); -# var length = _.max(_.pluck(args, 'length')); -# var results = new Array(length); -# for (var i=0; i 0 ? i - stop : stop - i) >= 0) return range; -# range[idx++] = i; -# } -# }; + _.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 => + return Math.min.apply(Math, obj) if not iterator and _.isArray(obj) + result: {computed: Infinity} + _.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 => + {value: value, criteria: iterator.call(context, value, index, list)} + ).sort() left, right => + a: left.criteria; b: right.criteria + if a < b then -1 else if a > b then 1 else 0 + ), '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 => + iterator ||= _.identity + low: 0; high: array.length + while low < high + mid: (low + high) >> 1 + if iterator(array[mid]) < iterator(obj) then low: mid + 1 else high: mid + low + + + # Convert anything iterable into a real, live array. + _.toArray: iterable => + return [] if (!iterable) + return iterable.toArray() if (iterable.toArray) + return iterable if (_.isArray(iterable)) + return slice.call(iterable) if (_.isArguments(iterable)) + _.values(iterable) + + + # Return the number of elements in an object. + _.size: obj => _.toArray(obj).length + + + # -------------------------- Array Functions: ------------------------------ + + # 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 => + if n and not guard then slice.call(array, 0, n) else array[0] + + + # Returns everything but the first entry of the array. Aliased as "tail". + # 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 => + 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] + + + # Trim out all falsy values from an array. + _.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 => + 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 => + 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 => + 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)) + memo + + + # Produce an array that contains every item shared between all the + # passed-in arrays. + _.intersect: array => + rest: _.rest(arguments) + _.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')) + results: new Array(length) + for i in [0...length] + results[i]: _.pluck(args, 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 => + return array.indexOf(item) if array.indexOf + i: 0; l: array.length + while l - i + if array[i] is item then return i else i++ + -1 + + + # Provide JavaScript 1.6's lastIndexOf, delegating to the native function, + # if possible. + _.lastIndexOf: array, item => + return array.lastIndexOf(item) if array.lastIndexOf + i: array.length + while i + if array[i] is item then return i else i-- + -1 + + + # 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) + solo: a.length <= 1 + i: start: if solo then 0 else a[0]; + stop: if solo then a[0] else a[1]; + step: a[2] or 1 + len: Math.ceil((stop - start) / step) + return [] if len <= 0 + range: new Array(len) + idx: 0 + while true + return range if (if step > 0 then i - stop else stop - i) >= 0 + range[idx]: i + idx++ + i+= step + # ----------------------- Function Functions: ----------------------------- @@ -313,34 +333,36 @@ _.reduceRight: obj, memo, iterator, context => # optionally). Binding with arguments is also known as 'curry'. _.bind: func, obj => args: _.rest(arguments, 2) - => func.apply(obj or root, args.concat(_.toArray(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 = function(obj) { -# var funcs = _.rest(arguments); -# if (funcs.length == 0) funcs = _.functions(obj); -# _.each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); -# return obj; -# }; -# -# # Delays a function for the given number of milliseconds, and then calls -# # it with the arguments supplied. -# _.delay = function(func, wait) { -# var args = _.rest(arguments, 2); -# return setTimeout(function(){ return func.apply(func, args); }, wait); -# }; + => func.apply(obj or root, args.concat(_.toArray(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 => + funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(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 => + args: _.rest(arguments, 2) + setTimeout((=> func.apply(func, args)), wait) + # Defers a function, scheduling it to run after the current call stack has # cleared. _.defer: func => - _.delay.apply(_, [func, 1].concat(_.rest(arguments))). + _.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))).. + => wrapper.apply(wrapper, [func].concat(_.toArray(arguments))) + # Returns a function that is the composition of a list of functions, each # consuming the return value of the function that follows. @@ -348,40 +370,48 @@ _.reduceRight: obj, memo, iterator, context => funcs: _.toArray(arguments) => args: _.toArray(arguments) - args: [funcs[i]].apply(this, args) for i in [(funcs.length - 1)..0]. - args[0].. - -# /* ------------------------- Object Functions: ---------------------------- */ -# -# # Retrieve the names of an object's properties. -# _.keys = function(obj) { -# if(_.isArray(obj)) return _.range(0, obj.length); -# var keys = []; -# for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key); -# return keys; -# }; -# -# # Retrieve the values of an object's properties. -# _.values = function(obj) { -# return _.map(obj, _.identity); -# }; -# -# # Return a sorted list of the function names available in Underscore. -# _.functions = function(obj) { -# return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort(); -# }; -# -# # Extend a given object with all of the properties in a source object. -# _.extend = function(destination, source) { -# for (var property in source) destination[property] = source[property]; -# return destination; -# }; -# -# # Create a (shallow-cloned) duplicate of an object. -# _.clone = function(obj) { -# if (_.isArray(obj)) return obj.slice(0); -# return _.extend({}, obj); -# }; + for i in [(funcs.length - 1)..0] + args: [funcs[i].apply(this, args)] + args[0] + + + # ------------------------- Object Functions: ---------------------------- + + # Retrieve the names of an object's properties. + _.keys: obj => + return _.range(0, obj.length) if _.isArray(obj) + key for val, key in obj + + + # Retrieve the values of an object's properties. + _.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() + + + # Extend a given object with all of the properties in a source object. + _.extend: destination, source => + for val, key in source + destination[key]: val + destination + + + # Create a (shallow-cloned) duplicate of an object. + _.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 => + interceptor(obj) + obj + # Perform a deep comparison to check if two objects are equal. _.isEqual: a, b => @@ -402,10 +432,10 @@ _.reduceRight: obj, memo, iterator, context => return true if _.isNaN(a) and _.isNaN(b) # Compare regular expressions. if _.isRegExp(a) and _.isRegExp(b) - return a.source is b.source and \ - a.global is b.global and \ - a.ignoreCase is b.ignoreCase and \ - a.multiline is b.multiline. + return a.source is b.source and + a.global is b.global and + a.ignoreCase is b.ignoreCase and + a.multiline is b.multiline # If a is not an object by this point, we can't handle it. return false if atype isnt 'object' # Check for different array lengths before comparing contents. @@ -416,42 +446,57 @@ _.reduceRight: obj, memo, iterator, context => return false if aKeys.length isnt bKeys.length # Recursive comparison of contents. # for (var key in a) if (!_.isEqual(a[key], b[key])) return false; - return true. + return true + # 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) + # 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 !_.isArray(obj) and !propertyIsEnumerable.call(obj, 'length') + + + # Is the given value a function? + _.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)) + + + # Is a given value a number? + _.isNumber: obj => toString.call(obj) is '[object Number]' + + + # Is a given value a Date? + _.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)) + # 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 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' - # 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 => - interceptor(obj) - obj. - -# # Define the isArray, isDate, isFunction, isNumber, isRegExp, and isString -# # functions based on their toString identifiers. -# var types = ['Array', 'Date', 'Function', 'Number', 'RegExp', 'String']; -# for (var i=0, l=types.length; i # previous owner. Returns a reference to the Underscore object. _.noConflict: => root._: previousUnderscore - this. + 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. - -# # Generate a unique integer id (unique within the entire client session). -# # Useful for temporary DOM ids. -# var idCounter = 0; -# _.uniqueId = function(prefix) { -# var id = idCounter++; -# return prefix ? prefix + id : id; -# }; -# -# # JavaScript templating a-la ERB, pilfered from John Resig's -# # "Secrets of the JavaScript Ninja", page 83. -# _.template = function(str, data) { -# var 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('');"); -# return data ? fn(data) : fn; -# }; + _.breakLoop: => throw breaker + + + # Generate a unique integer id (unique within the entire client session). + # Useful for temporary DOM ids. + idCounter: 0 + _.uniqueId: prefix => + (prefix or '') + idCounter++ + + + # 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', + '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('');")` + if data then fn(data) else fn + # ------------------------------- Aliases ---------------------------------- @@ -505,48 +552,42 @@ _.reduceRight: obj, memo, iterator, context => _.tail: _.rest _.methods: _.functions -# /*------------------------ Setup the OOP Wrapper: --------------------------*/ -# -# # Helper function to continue chaining intermediate results. -# var result = function(obj, chain) { -# return chain ? _(obj).chain() : obj; -# }; -# -# # Add all of the Underscore functions to the wrapper object. -# _.each(_.functions(_), function(name) { -# var method = _[name]; -# wrapper.prototype[name] = function() { -# unshift.call(arguments, this._wrapped); -# return result(method.apply(_, arguments), this._chain); -# }; -# }); -# -# # Add all mutator Array functions to the wrapper. -# _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { -# var method = Array.prototype[name]; -# wrapper.prototype[name] = function() { -# method.apply(this._wrapped, arguments); -# return result(this._wrapped, this._chain); -# }; -# }); -# -# # Add all accessor Array functions to the wrapper. -# _.each(['concat', 'join', 'slice'], function(name) { -# var method = Array.prototype[name]; -# wrapper.prototype[name] = function() { -# return result(method.apply(this._wrapped, arguments), this._chain); -# }; -# }); -# -# # Start chaining a wrapped Underscore object. -# wrapper.prototype.chain = function() { -# this._chain = true; -# return this; -# }; -# -# # Extracts the result from a wrapped and chained object. -# wrapper.prototype.value = function() { -# return this._wrapped; -# }; -# -# () + + # /*------------------------ Setup the OOP Wrapper: --------------------------*/ + + # Helper function to continue chaining intermediate results. + result: obj, chain => + if chain then _(obj).chain() else obj + + + # Add all of the Underscore functions to the wrapper object. + _.each(_.functions(_)) name => + method: _[name] + 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 => + method: Array.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 => + method: Array.prototype[name] + wrapper.prototype[name]: => + result(method.apply(this._wrapped, arguments), this._chain) + + + # Start chaining a wrapped Underscore object. + wrapper.prototype.chain: => + this._chain: true + this + + + # Extracts the result from a wrapped and chained object. + wrapper.prototype.value: => this._wrapped diff --git a/index.html b/index.html index ce203fdfbb..3dcc294df9 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,8 @@ + + @@ -35,23 +37,31 @@

CoffeeScript

preserved intact.

+

+ Latest Version: + 0.2.0 +

+

Table of Contents

Mini Overview
Installation and Usage
- Punctuation Primer
+ Significant Whitespace
Functions and Invocation
Assignment
Objects and Arrays
Lexical Scoping and Variable Safety
Conditionals, Ternaries, and Conditional Assignment
- Everything is an Expression
+ The Existence Operator
Aliases
+ Splats
While Loops
- Array Comprehensions
- Slicing Arrays with Ranges
+ Comprehensions (Arrays, Objects, and Ranges)
+ Array Slicing and Splicing with Ranges
+ Everything is an Expression
Inheritance, and Calling Super from a Subclass
+ Blocks
Embedded JavaScript
Switch/When/Else
Try/Catch/Finally
@@ -60,7 +70,7 @@

Table of Contents

Contributing
Change Log

- +

Mini Overview

CoffeeScript on the left, compiled JavaScript output on the right.

@@ -73,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] @@ -82,12 +92,19 @@

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) + +# Existence: +alert("I knew it!") if elvis? + # Array comprehensions: -cubed_list: math.cube(num) for num in list. -
var __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, square;
+cubed_list: math.cube(num) for num in list
+
var __a, __b, __c, __d, cubed_list, list, math, num, number, opposite_day, race, square;
 // Assignment:
 number = 42;
 opposite_day = true;
@@ -96,7 +113,7 @@ 

Mini Overview

number = -42; } // Functions: -square = function(x) { +square = function square(x) { return x * x; }; // Arrays: @@ -105,19 +122,34 @@

Mini Overview

math = { root: Math.sqrt, square: square, - cube: function(x) { + cube: function cube(x) { return x * square(x); } }; -// Array comprehensions: -__a = list; -__d = []; -for (__b=0, __c=__a.length; __b<__c; __b++) { - num = __a[__b]; - __d[__b] = math.cube(num); +// Splats: +race = function race(winner) { + var runners; + runners = Array.prototype.slice.call(arguments, 1); + return print(winner, runners); +}; +// Existence: +if ((typeof elvis !== "undefined" && elvis !== null)) { + alert("I knew it!"); } -cubed_list = __d; -

+

+ For a longer CoffeeScript example, check out + Underscore.coffee, a port + of Underscore.js + to CoffeeScript, which, when compiled, can pass the complete Underscore test suite. + Or, clone the source and take a look in the + examples folder. +

+

Installation and Usage

@@ -181,7 +237,7 @@

Installation and Usage

-r, --run - Compile and execute the CoffeeScripts without saving the intermediate + Compile and execute scripts without saving the intermediate JavaScript. Requires Narwhal. @@ -217,7 +273,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" @@ -273,37 +329,38 @@

Language Reference

-

- Punctuation Primer - You don't need to use semicolons ; to terminate expressions, ending - the line will do just as well. All other whitespace is - not significant. Instead of using curly braces { } - to delimit a block of code, use a period . to mark the end of a - block, for - functions, +

+ Significant Whitespace + CoffeeScript uses Python-style significant whitespace: You don't need to + use semicolons ; to terminate expressions, ending + the line will do just as well. Semicolons can still be used to fit + multiple expressions onto a single line. Instead of using curly braces + { } to delimit blocks of code (like functions, if-statements, - switch, and try/catch. + switch, and try/catch), + use indentation.

Functions and Invocation Functions are defined by a list of parameters, an arrow, and the - function body. The empty function looks like this: =>. + function body. The empty function looks like this: =>. All + functions in CoffeeScript are named, for the benefit of debug messages.

-
square: x => x * x.
-cube:   x => square(x) * x.
+    
square: x => x * x
+cube:   x => square(x) * x
 
var cube, square;
-square = function(x) {
+square = function square(x) {
   return x * x;
 };
-cube = function(x) {
+cube = function cube(x) {
   return square(x) * x;
 };
 

@@ -324,8 +381,8 @@

Language Reference

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

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

@@ -333,28 +390,38 @@

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. + assigning local variables, and can be moved around freely. You can mix + and match the two styles.

song: ["do", "re", "mi", "fa", "so"]
+
 ages: {
   max: 10
   ida: 9
   tim: 11
 }
-
var ages, song;
+
+matrix: [
+  1, 0, 1
+  0, 0, 1
+  1, 1, 0
+]
+
var ages, matrix, song;
 song = ["do", "re", "mi", "fa", "so"];
 ages = {
   max: 10,
   ida: 9,
   tim: 11
 };
-

@@ -365,46 +432,50 @@

Language Reference

num: 1
 change_numbers: =>
-  num: 2
-  new_num: 3.
+  new_num: -1
+  num: 10
 new_num: change_numbers()
 
var change_numbers, new_num, num;
 num = 1;
-change_numbers = function() {
+change_numbers = function change_numbers() {
   var new_num;
-  num = 2;
-  return (new_num = 3);
+  new_num = -1;
+  return num = 10;
 };
 new_num = change_numbers();
 

- Notice how the variables are declared with var the first time - they appear. The second reference of num, within the function, - is not redeclared because num is still in scope. As opposed - to the second occurrence of new_num, in the last line. + Notice how the all of the variable declarations have been pushed up to + the top of the closest scope, the first time they appear. + num is not redeclared within the inner function, because it's + already in scope; the new_num within the function, on the other hand, + should not be able to change the value of the external variable of the same name, and + therefore has a declaration of its own.

Although suppressed within this documentation for clarity, all 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. + 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.

Conditionals, Ternaries, and Conditional Assignment - If/else statements can be written without the use of parenthesis and - curly brackets. As with functions and other block expressions, conditionals - are closed with periods. No period is necessary when using the single-line - postfix form, with the if at the end. + If/else statements can be written without the use of parentheses and + curly brackets. As with functions and other block expressions, + multi-line conditionals are delimited by indentation. There's also a handy + postfix form, with the if or unless at the end.

CoffeeScript will compile if statements using the ternary operator @@ -414,9 +485,9 @@

Language Reference

if happy and knows_it claps_hands() - cha_cha_cha(). + cha_cha_cha() -date: if friday then sue else jill. +date: if friday then sue else jill expensive ||= do_the_math()
var date, mood;
@@ -431,67 +502,26 @@ 

Language Reference

expensive = expensive || do_the_math();

- The conditional assignment operators are available: ||=, + The conditional assignment operators are included: ||=, which only assigns a value to a variable if the variable's current value is falsy, and &&=, which only replaces the value of truthy variables.

-

- Everything is an Expression (at least, as much as possible) - You might have noticed how even though we don't add return statements - to CoffeeScript functions, they nonetheless return their final value. - The CoffeeScript compiler tries to make sure that all statements in the - language can be used as expressions. Watch how the return gets - pushed down into each possible branch of execution, in the function - below. +

+ The Existence 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 existence operator ? returns true unless + a variable is null or undefined, which makes it analogous + to Ruby's nil?

-
grade: student =>
-  if student.excellent_work
-    "A+"
-  else if student.okay_stuff
-    if student.tried_hard then "B" else "B-".
-  else
-    "C"..
-
-eldest: if 24 > 21 then "Liz" else "Ike".
-
var eldest, grade;
-grade = function(student) {
-  if (student.excellent_work) {
-    return "A+";
-  } else if (student.okay_stuff) {
-    return student.tried_hard ? "B" : "B-";
-  } else {
-    return "C";
-  }
-};
-eldest = 24 > 21 ? "Liz" : "Ike";
-

-

- The same mechanism is used to push down assignment through switch - statements, and if-elses (although the ternary operator is preferred). - Another part of manipulating assignment statements is - CoffeeScript's declaration of new variables at the top of the - current scope. This allows assignment to be used as a piece of an - expression. -

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

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

Aliases @@ -527,7 +557,7 @@

Language Reference

let_the_wild_rumpus_begin() unless answer is no -if car.speed < speed_limit then accelerate(). +if car.speed < speed_limit then accelerate()
var volume;
 if (ignition === true) {
   launch();
@@ -541,15 +571,77 @@ 

Language Reference

car.speed < speed_limit ? accelerate() : null;

+

+ Splats + 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. +

+
gold: silver: the_field: "unknown"
+
+medalists: first, second, *rest =>
+  gold:       first
+  silver:     second
+  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(*contenders)
+
+alert("Gold: " + gold)
+alert("Silver: " + silver)
+alert("The Field: " + the_field)
+
var contenders, gold, medalists, silver, the_field;
+gold = silver = the_field = "unknown";
+medalists = function medalists(first, second) {
+  var rest;
+  rest = Array.prototype.slice.call(arguments, 2);
+  gold = first;
+  silver = second;
+  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);
+alert("Gold: " + gold);
+alert("Silver: " + silver);
+alert("The Field: " + the_field);
+

+

While Loops The only low-level loop that CoffeeScript provides is the while loop.

while demand > supply
   sell()
-  restock().
+  restock()
 
-while supply > demand then buy().
+while supply > demand then buy()
 
while (demand > supply) {
   sell();
   restock();
@@ -565,8 +657,8 @@ 

Language Reference

each (forEach) style iterators, or...

-

- Array Comprehensions +

+ Comprehensions (Arrays, Objects, and Ranges) For your looping needs, CoffeeScript provides array comprehensions similar to Python's. They replace (and compile into) for loops, with optional guard clauses and the value of the current array index. @@ -575,37 +667,108 @@

Language Reference

would use a loop, each/forEach, map, or select/filter.

# Eat lunch.
-lunch: food.eat() for food in ['toast', 'cheese', 'wine'].
+lunch: eat(food) for food in ['toast', 'cheese', 'wine']
 
-# Zebra-stripe a table.
-highlight(row) for row, i in table if i % 2 is 0.
-
var __a, __b, __c, __d, __e, __f, __g, __h, food, i, lunch, row;
+# Naive collision detection.
+for roid in asteroids
+  for roid2 in asteroids when roid isnt roid2
+    roid.explode() if roid.overlaps(roid2)
+
var __a, __b, __c, __d, __e, __f, __g, __h, __i, __j, food, lunch, roid, roid2;
 // Eat lunch.
-__a = ['toast', 'cheese', 'wine'];
-__d = [];
-for (__b=0, __c=__a.length; __b<__c; __b++) {
-  food = __a[__b];
-  __d[__b] = food.eat();
+lunch = (function() {
+  __a = ['toast', 'cheese', 'wine'];
+  __c = [];
+  for (__b in __a) {
+    if (__a.hasOwnProperty(__b)) {
+      food = __a[__b];
+      __d = eat(food);
+      __c.push(__d);
+    }
+  }
+  return __c;
+})();
+// Naive collision detection.
+__e = asteroids;
+for (__f in __e) {
+  if (__e.hasOwnProperty(__f)) {
+    roid = __e[__f];
+    __h = asteroids;
+    for (__i in __h) {
+      if (__h.hasOwnProperty(__i)) {
+        roid2 = __h[__i];
+        if (roid !== roid2) {
+          if (roid.overlaps(roid2)) {
+            roid.explode();
+          }
+        }
+      }
+    }
+  }
 }
-lunch = __d;
-// Zebra-stripe a table.
-__e = table;
-__h = [];
-for (__f=0, __g=__e.length; __f<__g; __f++) {
-  row = __e[__f];
-  i = __f;
-  __h[__f] = i % 2 === 0 ? highlight(row) : null;
+

+

+ If you know the start and end of your loop, or would like to step through + in fixed-size increments, you can use a range to specify the start and + end of your comprehension: +

+
for i in [0...eggs.length] by 12
+  dozen_eggs: eggs[i...i+12]
+  deliver(new egg_carton(dozen))
+
var __a, __b, __c, __d, __e, dozen_eggs, i;
+__d = 0;
+__e = eggs.length;
+for (__c=0, i=__d; (__d <= __e ? i < __e : i > __e); (__d <= __e ? i += 12 : i -= 12), __c++) {
+  dozen_eggs = eggs.slice(i, i + 12);
+  deliver(new egg_carton(dozen));
 }
-__h;
 

- If you're not iterating over an actual array, you can use a range to - specify the start and end of an array comprehension: - coundown(i) for i in [10..1]. + Comprehensions can also be used to iterate over the values and keys in + an object:

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

-

- Slicing Arrays with Ranges +

+ Array Slicing and Splicing with Ranges CoffeeScript borrows Ruby's range syntax for extracting slices of arrays. With two dots (3..5), the range @@ -628,6 +791,137 @@

Language Reference

three_to_six = numbers.slice(3, 6 + 1); numbers_copy = numbers.slice(0, numbers.length); ;alert(numbers_copy);'>run: numbers_copy
+

+ The same syntax can be used with assignment to replace a segment of an + array with new values (to splice it). +

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

+ +

+ Everything is an Expression (at least, as much as possible) + You might have noticed how even though we don't add return statements + to CoffeeScript functions, they nonetheless return their final value. + The CoffeeScript compiler tries to make sure that all statements in the + language can be used as expressions. Watch how the return gets + pushed down into each possible branch of execution, in the function + below. +

+
grade: student =>
+  if student.excellent_work
+    "A+"
+  else if student.okay_stuff
+    if student.tried_hard then "B" else "B-"
+  else
+    "C"
+
+eldest: if 24 > 21 then "Liz" else "Ike"
+
var eldest, grade;
+grade = function grade(student) {
+  if (student.excellent_work) {
+    return "A+";
+  } else if (student.okay_stuff) {
+    return student.tried_hard ? "B" : "B-";
+  } else {
+    return "C";
+  }
+};
+eldest = 24 > 21 ? "Liz" : "Ike";
+

+

+ Because variable declarations occur at the top of scope, assignment can + be used within expressions, even for variables that haven't been seen before: +

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

+

+ Things that would otherwise be statements in JavaScript, when used + as part of an expression in CoffeeScript, are converted into expressions + by wrapping them in a closure. This lets you do useful things, like assign + the result of a comprehension to a variable: +

+
# The first ten global properties.
+
+globals: (name for property, name in window)[0...10]
+
var __a, __b, __c, globals, name, property;
+// The first ten global properties.
+globals = ((function() {
+  __a = window;
+  __b = [];
+  for (name in __a) {
+    if (__a.hasOwnProperty(name)) {
+      property = __a[name];
+      __c = name;
+      __b.push(__c);
+    }
+  }
+  return __b;
+})()).slice(0, 10);
+

+

+ As well as silly things, like passing a try/catch statement directly + into a function call: +

+
alert(
+  try
+    nonexistent / undefined
+  catch error
+    "The error is: " + error
+)
+
alert((function() {
+  try {
+    return nonexistent / undefined;
+  } catch (error) {
+    return "The error is: " + error;
+  }
+})());
+

Inheritance, and Calling Super from a Subclass @@ -646,21 +940,21 @@

Language Reference

super() calls into calls against the immediate ancestor's method of the same name.

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

Language Reference

var Animal, Horse, Snake, sam, tom;
-Animal = function() {
+Animal = function Animal() {
 };
-Animal.prototype.move = function(meters) {
+Animal.prototype.move = function move(meters) {
   return alert(this.name + " moved " + meters + "m.");
 };
-Snake = function(name) {
-  return (this.name = name);
+Snake = function Snake(name) {
+  return this.name = name;
 };
 Snake.__superClass__ = Animal.prototype;
 Snake.prototype = new Animal();
 Snake.prototype.constructor = Snake;
-Snake.prototype.move = function() {
+Snake.prototype.move = function move() {
   alert("Slithering...");
   return Snake.__superClass__.move.call(this, 5);
 };
-Horse = function(name) {
-  return (this.name = name);
+Horse = function Horse(name) {
+  return this.name = name;
 };
 Horse.__superClass__ = Animal.prototype;
 Horse.prototype = new Animal();
 Horse.prototype.constructor = Horse;
-Horse.prototype.move = function() {
+Horse.prototype.move = function move() {
   alert("Galloping...");
   return Horse.__superClass__.move.call(this, 45);
 };
@@ -702,28 +996,28 @@ 

Language Reference

sam.move(); tom.move();

+

+ 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();
+  });
+});
+

+

Embedded JavaScript If you ever need to interpolate literal JavaScript snippets, you can @@ -764,14 +1077,14 @@

Language Reference

when clauses, else the default case.

switch day
-when "Tuesday"   then eat_breakfast()
-when "Wednesday" then go_to_the_park()
-when "Saturday"
-  if day is bingo_day
-    go_to_bingo()
-    go_dancing().
-when "Sunday"    then go_to_church()
-else go_to_work().
+  when "Tuesday"   then eat_breakfast()
+  when "Wednesday" then go_to_the_park()
+  when "Saturday"
+    if day is bingo_day
+      go_to_bingo()
+      go_dancing()
+  when "Sunday"    then go_to_church()
+  else go_to_work()
 
if (day === "Tuesday") {
   eat_breakfast();
 } else if (day === "Wednesday") {
@@ -799,7 +1112,7 @@ 

Language Reference

catch error print(error) finally - clean_up(). + clean_up()
try {
   all_hell_breaks_loose();
   cats_and_dogs_living_together();
@@ -810,7 +1123,7 @@ 

Language Reference

}

-

+

Multiline Strings Multiline strings are allowed in CoffeeScript.

@@ -837,13 +1150,27 @@

Language Reference

about a little and see the watery part of the \ world..."; ;alert(moby_dick);'>run: moby_dick
- +

Resources

- -

- Source Code
- Bugs and Feature Requests
-

+ +

Contributing

@@ -854,13 +1181,13 @@

Contributing

Change Log

- + +

+ 0.2.0 + Major release. Significant whitespace. Better statement-to-expression + conversion. Splats. Splice literals. Object comprehensions. Blocks. + The existence operator. Many thanks to all the folks who posted issues, + with special thanks to + Liam O'Connor-Davis for whitespace + and expression help. +

+

0.1.6 Bugfix for running coffee --interactive and --run - from outside of the CoffeeScript directory. Bugfix for nested - function/if-statements. + from outside of the CoffeeScript directory. Bugfix for nested + function/if-statements.

- +

0.1.5 Array slice literals and array comprehensions can now both take Ruby-style - ranges to specify the start and end. JavaScript variable declaration is - now pushed up to the top of the scope, making all assignment statements into + ranges to specify the start and end. JavaScript variable declaration is + now pushed up to the top of the scope, making all assignment statements into expressions. You can use \ to escape newlines. The coffee-script command is now called coffee.

diff --git a/lib/coffee-script.rb b/lib/coffee-script.rb index afae2b500d..287378c559 100644 --- a/lib/coffee-script.rb +++ b/lib/coffee-script.rb @@ -4,12 +4,13 @@ require "coffee_script/nodes" require "coffee_script/value" require "coffee_script/scope" +require "coffee_script/rewriter" require "coffee_script/parse_error" # Namespace for all CoffeeScript internal classes. module CoffeeScript - VERSION = '0.1.6' # Keep in sync with the gemspec. + VERSION = '0.2.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/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage b/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage index 990a236823..2ff3cd30d3 100644 --- a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage +++ b/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage @@ -39,7 +39,7 @@ comment match stuff like: funcName: => … match - ([a-zA-Z_?.$]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>) + ([a-zA-Z0-9_?.$*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>) name meta.function.coffee @@ -60,7 +60,7 @@ comment match stuff like: a => … match - ([a-zA-Z_?., $]*)\s*(=>) + ([a-zA-Z0-9_?., $*]*)\s*(=>) name meta.inline.function.coffee @@ -204,10 +204,29 @@ match - \b(break|when|catch|continue|else|finally|for|if|return|switch|then|throw|try|unless|while)\b + \b(break|by|catch|continue|else|finally|for|if|return|switch|then|throw|try|unless|when|while)\b name keyword.control.coffee + + match + \b([a-zA-Z$_]\w*)(\:)\s + name + variable.assignment.coffee + captures + + 1 + + name + entity.name.function.coffee + + 2 + + name + keyword.operator.coffee + + + match \b(true|on|yes)\b @@ -240,7 +259,7 @@ match - !|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|and|or|is|isnt|not)\b + !|\$|%|&|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|and|or|is|isnt|not)\b name keyword.operator.coffee diff --git a/lib/coffee_script/command_line.rb b/lib/coffee_script/command_line.rb index 1074d91176..bf7481b051 100644 --- a/lib/coffee_script/command_line.rb +++ b/lib/coffee_script/command_line.rb @@ -19,8 +19,9 @@ class CommandLine # Seconds to pause between checks for changed source files. WATCH_INTERVAL = 0.5 - # Path to the Narwhal Launcher: - LAUNCHER = File.expand_path(File.dirname(__FILE__)) + '/narwhal/js/launcher.js' + # Command to execute in Narwhal + PACKAGE = File.expand_path(File.dirname(__FILE__) + '/../..') + LAUNCHER = "narwhal -p #{PACKAGE} -e 'require(\"coffee-script\").run(system.args);'" # Run the CommandLine off the contents of ARGV. def initialize @@ -107,7 +108,7 @@ def eval_scriptlet # Use Narwhal to run an interactive CoffeeScript session. def launch_repl - exec "narwhal #{LAUNCHER}" + exec "#{LAUNCHER}" rescue Errno::ENOENT puts "Error: Narwhal must be installed to use the interactive REPL." exit(1) @@ -116,7 +117,7 @@ def launch_repl # Use Narwhal to compile and execute CoffeeScripts. def run_scripts sources = @sources.join(' ') - exec "narwhal #{LAUNCHER} #{sources}" + exec "#{LAUNCHER} #{sources}" rescue Errno::ENOENT puts "Error: Narwhal must be installed in order to execute CoffeeScripts." exit(1) diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index a0946f65bc..105ac1100a 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -1,24 +1,26 @@ class Parser # Declare tokens produced by the lexer -token IF ELSE THEN UNLESS +token IF ELSE UNLESS token NUMBER STRING REGEX token TRUE FALSE YES NO ON OFF token IDENTIFIER PROPERTY_ACCESS -token CODE PARAM NEW RETURN +token CODE PARAM PARAM_SPLAT NEW RETURN token TRY CATCH FINALLY THROW token BREAK CONTINUE -token FOR IN WHILE -token SWITCH WHEN +token FOR IN BY WHEN WHILE +token SWITCH LEADING_WHEN token DELETE INSTANCEOF TYPEOF token SUPER EXTENDS token NEWLINE token COMMENT token JS +token INDENT OUTDENT # Declare order of operations. prechigh - nonassoc UMINUS NOT '!' '!!' '~' '++' '--' + left '?' + nonassoc UMINUS PARAM_SPLAT SPLAT NOT '!' '!!' '~' '++' '--' left '*' '/' '%' left '+' '-' left '<<' '>>' '>>>' @@ -29,51 +31,40 @@ prechigh right '-=' '+=' '/=' '*=' '%=' right DELETE INSTANCEOF TYPEOF left '.' - right THROW FOR IN WHILE NEW SUPER - left UNLESS IF ELSE EXTENDS + right INDENT + left OUTDENT + right WHEN LEADING_WHEN IN BY + right THROW FOR NEW SUPER + left EXTENDS left ASSIGN '||=' '&&=' - right RETURN + right RETURN '=>' UNLESS IF ELSE WHILE preclow -# We expect 3 shift/reduce errors for optional syntax. -# There used to be 252 -- greatly improved. -expect 3 - rule # All parsing will end in this rule, being the trunk of the AST. Root: - /* nothing */ { result = Expressions.new([]) } - | Terminator { result = Expressions.new([]) } + /* nothing */ { result = Expressions.new } + | Terminator { result = Expressions.new } | Expressions { result = val[0] } + | Block Terminator { result = val[0] } ; # Any list of expressions or method body, seperated by line breaks or semis. Expressions: - Expression { result = Expressions.new(val) } + Expression { result = Expressions.wrap(val) } | Expressions Terminator Expression { result = val[0] << val[2] } | Expressions Terminator { result = val[0] } - | Terminator Expressions { result = val[1] } ; # All types of expressions in our language. Expression: - PureExpression - | Statement - ; - - # The parts that are natural JavaScript expressions. - PureExpression: Value | Call | Code | Operation | Range - ; - - # We have to take extra care to convert these statements into expressions. - Statement: - Assign + | Assign | If | Try | Throw @@ -82,21 +73,22 @@ rule | For | Switch | Extends + | Splat + | Existence | Comment ; + Block: + INDENT Expressions OUTDENT { result = val[1] } + | INDENT OUTDENT { result = Expressions.new } + ; + # All tokens that can terminate an expression. Terminator: "\n" | ";" ; - # All tokens that can serve to begin the second block of a multi-part expression. - Then: - THEN - | Terminator - ; - # All hard-coded values. Literal: NUMBER { result = LiteralNode.new(val[0]) } @@ -115,13 +107,13 @@ rule # Assignment to a variable. Assign: - Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) } + Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) } ; # Assignment within an object literal. AssignObj: - IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) } - | STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) } + IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) } + | STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) } | Comment { result = val[0] } ; @@ -146,6 +138,8 @@ rule | '~' Expression { result = OpNode.new(val[0], val[1]) } | '--' Expression { result = OpNode.new(val[0], val[1]) } | '++' Expression { result = OpNode.new(val[0], val[1]) } + | DELETE Expression { result = OpNode.new(val[0], val[1]) } + | TYPEOF Expression { result = OpNode.new(val[0], val[1]) } | Expression '--' { result = OpNode.new(val[1], val[0], nil, true) } | Expression '++' { result = OpNode.new(val[1], val[0], nil, true) } @@ -187,27 +181,32 @@ rule | Expression '||=' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '&&=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | DELETE Expression { result = OpNode.new(val[0], val[1]) } - | TYPEOF Expression { result = OpNode.new(val[0], val[1]) } | Expression INSTANCEOF Expression { result = OpNode.new(val[1], val[0], val[2]) } ; - # Function definition. - Code: - ParamList "=>" CodeBody "." { result = CodeNode.new(val[0], val[2]) } - | "=>" CodeBody "." { result = CodeNode.new([], val[1]) } + Existence: + Expression '?' { result = ExistenceNode.new(val[0]) } ; - # The body of a function. - CodeBody: - /* nothing */ { result = Expressions.new([]) } - | Expressions { result = val[0] } + # Function definition. + Code: + ParamList "=>" Block { result = CodeNode.new(val[0], val[2]) } + | "=>" Block { result = CodeNode.new([], val[1]) } ; # The parameters to a function definition. ParamList: - PARAM { result = val } - | ParamList "," PARAM { result = val[0] << val[2] } + Param { result = val } + | ParamList "," Param { result = val[0] << val[2] } + ; + + Param: + PARAM + | PARAM_SPLAT PARAM { result = ParamSplatNode.new(val[1]) } + ; + + Splat: + '*' Value = SPLAT { result = ArgSplatNode.new(val[1]) } ; # Expressions that can be treated as values. @@ -240,10 +239,13 @@ rule # Assignment within an object literal (comma or newline separated). AssignList: - /* nothing */ { result = []} + /* nothing */ { result = [] } | AssignObj { result = val } | AssignList "," AssignObj { result = val[0] << val[2] } | AssignList Terminator AssignObj { result = val[0] << val[2] } + | AssignList "," + Terminator AssignObj { result = val[0] << val[3] } + | INDENT AssignList OUTDENT { result = val[1] } ; # All flavors of function call (instantiation, super, and regular). @@ -260,8 +262,14 @@ rule # A generic function invocation. Invocation: - Value "(" ArgList ")" { result = CallNode.new(val[0], val[2]) } - | Invocation "(" ArgList ")" { result = CallNode.new(val[0], val[2]) } + Value Arguments { result = CallNode.new(val[0], val[1]) } + | Invocation Arguments { result = CallNode.new(val[0], val[1]) } + # | Invocation Code { result = val[0] << val[1] } + ; + + Arguments: + "(" ArgList ")" { result = val[1] } + | "(" ArgList ")" Code { result = val[1] << val[3] } ; # Calling super. @@ -271,8 +279,10 @@ rule # The range literal. Range: - "[" Value "." "." Value "]" { result = RangeNode.new(val[1], val[4]) } - | "[" Value "." "." "." Value "]" { result = RangeNode.new(val[1], val[5], true) } + "[" Expression + "." "." Expression "]" { result = RangeNode.new(val[1], val[4]) } + | "[" Expression + "." "." "." Expression "]" { result = RangeNode.new(val[1], val[5], true) } ; # The array literal. @@ -284,21 +294,25 @@ rule ArgList: /* nothing */ { result = [] } | Expression { result = val } + | INDENT Expression { result = [val[1]] } | ArgList "," Expression { result = val[0] << val[2] } | ArgList Terminator Expression { result = val[0] << val[2] } + | ArgList "," Terminator Expression { result = val[0] << val[3] } + | ArgList "," INDENT Expression { result = val[0] << val[3] } + | ArgList OUTDENT { result = val[0] } ; # Try/catch/finally exception handling blocks. Try: - TRY Expressions Catch "." { result = TryNode.new(val[1], val[2][0], val[2][1]) } - | TRY Expressions Catch - FINALLY Expressions "." { result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) } + TRY Block Catch { result = TryNode.new(val[1], val[2][0], val[2][1]) } + | TRY Block FINALLY Block { result = TryNode.new(val[1], nil, nil, val[3]) } + | TRY Block Catch + FINALLY Block { result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) } ; # A catch clause. Catch: - /* nothing */ { result = [nil, nil] } - | CATCH IDENTIFIER Expressions { result = [val[1], val[2]] } + CATCH IDENTIFIER Block { result = [val[1], val[2]] } ; # Throw an exception. @@ -308,20 +322,20 @@ rule # Parenthetical expressions. Parenthetical: - "(" Expressions ")" { result = ParentheticalNode.new(val[1]) } + "(" Expression ")" { result = ParentheticalNode.new(val[1], val[0].line) } ; # The while loop. (there is no do..while). While: - WHILE Expression Then - Expressions "." { result = WhileNode.new(val[1], val[3]) } + WHILE Expression Block { result = WhileNode.new(val[1], val[2]) } ; # Array comprehensions, including guard and current index. # Looks a little confusing, check nodes.rb for the arguments to ForNode. For: Expression FOR - ForVariables ForSource { result = ForNode.new(val[0], val[3][0], val[2][0], val[3][1], val[2][1]) } + ForVariables ForSource { result = ForNode.new(val[0], val[3], val[2][0], val[2][1]) } + | FOR ForVariables ForSource Block { result = ForNode.new(val[3], val[2], val[1][0], val[1][1]) } ; # An array comprehension has variables for the current element and index. @@ -332,17 +346,19 @@ rule # The source of the array comprehension can optionally be filtered. ForSource: - IN PureExpression "." { result = [val[1]] } - | IN PureExpression - IF Expression "." { result = [val[1], val[3]] } + IN Expression { result = {:source => val[1]} } + | ForSource + WHEN Expression { result = val[0].merge(:filter => val[2]) } + | ForSource + BY Expression { result = val[0].merge(:step => val[2]) } ; # Switch/When blocks. Switch: - SWITCH Expression Then - Whens "." { result = val[3].rewrite_condition(val[1]) } - | SWITCH Expression Then - Whens ELSE Expressions "." { result = val[3].rewrite_condition(val[1]).add_else(val[5]) } + SWITCH Expression INDENT + Whens OUTDENT { result = val[3].rewrite_condition(val[1]) } + | SWITCH Expression INDENT + Whens ELSE Block OUTDENT { result = val[3].rewrite_condition(val[1]).add_else(val[5]) } ; # The inner list of whens. @@ -353,16 +369,22 @@ rule # An individual when. When: - WHEN Expression Then Expressions { result = IfNode.new(val[1], val[3]) } + LEADING_WHEN Expression Block { result = IfNode.new(val[1], val[2], nil, {:statement => true}) } + | LEADING_WHEN Expression Block + Terminator { result = IfNode.new(val[1], val[2], nil, {:statement => true}) } + | Comment ; # All of the following nutso if-else destructuring is to make the # grammar expand unambiguously. + IfBlock: + IF Expression Block { result = IfNode.new(val[1], val[2]) } + ; + # An elsif portion of an if-else block. ElsIf: - ELSE IF Expression - Then Expressions { result = IfNode.new(val[2], val[4]) } + ELSE IfBlock { result = val[1].force_statement } ; # Multiple elsifs can be chained together. @@ -373,8 +395,8 @@ rule # Terminating else bodies are strictly optional. ElseBody - "." { result = nil } - | ELSE Expressions "." { result = val[1] } + /* nothing */ { result = nil } + | ELSE Block { result = val[1] } ; # All the alternatives for ending an if-else block. @@ -385,10 +407,9 @@ rule # The full complement of if blocks, including postfix one-liner ifs and unlesses. If: - IF Expression - Then Expressions IfEnd { result = IfNode.new(val[1], val[3], val[4]) } - | Expression IF Expression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true}) } - | Expression UNLESS Expression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true, :invert => true}) } + IfBlock IfEnd { result = val[0].add_else(val[1]) } + | Expression IF Expression { result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true}) } + | Expression UNLESS Expression { result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true, :invert => true}) } ; end diff --git a/lib/coffee_script/lexer.rb b/lib/coffee_script/lexer.rb index 2e6d95ec9b..f67cddbd10 100644 --- a/lib/coffee_script/lexer.rb +++ b/lib/coffee_script/lexer.rb @@ -12,69 +12,80 @@ class Lexer "new", "return", "try", "catch", "finally", "throw", "break", "continue", - "for", "in", "while", + "for", "in", "by", "where", "while", "switch", "when", "super", "extends", "delete", "instanceof", "typeof"] # 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 + NUMBER = /\A(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i STRING = /\A(""|''|"(.*?)[^\\]"|'(.*?)[^\\]')/m JS = /\A(``|`(.*?)[^\\]`)/m OPERATOR = /\A([+\*&|\/\-%=<>:!]+)/ - WHITESPACE = /\A([ \t\r]+)/ - NEWLINE = /\A(\n+)/ - COMMENT = /\A((#[^\n]*\s*)+)/m + WHITESPACE = /\A([ \t]+)/ + COMMENT = /\A(((\n?[ \t]*)?#.*$)+)/ CODE = /\A(=>)/ REGEX = /\A(\/(.*?)[^\\]\/[imgy]{0,4})/ + MULTI_DENT = /\A((\n([ \t]*)?)+)/ + LAST_DENT = /\n([ \t]*)/ + ASSIGNMENT = /\A(:|=)\Z/ # Token cleaning regexes. JS_CLEANER = /(\A`|`\Z)/ MULTILINER = /\n/ COMMENT_CLEANER = /(^\s*#|\n\s*$)/ + NO_NEWLINE = /\A([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)\Z/ - # Tokens that always constitute the start of an expression. - EXP_START = ['{', '(', '['] - - # Tokens that always constitute the end of an expression. - EXP_END = ['}', ')', ']'] - - # Assignment tokens. - ASSIGN = [':', '='] + # Tokens which a regular expression will never immediately follow, but which + # a division operator might. + # See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions + NOT_REGEX = [ + :IDENTIFIER, :NUMBER, :REGEX, :STRING, + ')', '++', '--', ']', '}', + :FALSE, :NULL, :THIS, :TRUE + ] # 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 @i = 0 # Current character position we're parsing @line = 1 # The current line. + @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] while @i < @code.length @chunk = @code[@i..-1] extract_next_token end - @tokens + puts "original stream: #{@tokens.inspect}" if ENV['VERBOSE'] + close_indentation + Rewriter.new.rewrite(@tokens) end - # At every position, run this list of match attempts, short-circuiting if - # any of them succeed. + # At every position, run through this list of attempted matches, + # short-circuiting if any of them succeed. def extract_next_token return if identifier_token return if number_token return if string_token return if js_token return if regex_token + return if indent_token return if comment_token return if whitespace_token return literal_token end + # Tokenizers ========================================================== + # Matches identifying literals: variables, keywords, method names, etc. def identifier_token return false unless identifier = @chunk[IDENTIFIER, 1] - # Keywords are special identifiers tagged with their own name, 'if' will result - # in an [:IF, "if"] token + # Keywords are special identifiers tagged with their own name, + # '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][1] == '.') token(tag, identifier) @i += identifier.length @@ -108,6 +119,7 @@ def js_token # Matches regular expression literals. def regex_token return false unless regex = @chunk[REGEX, 1] + return false if NOT_REGEX.include?(last_tag) token(:REGEX, regex) @i += regex.length end @@ -121,73 +133,105 @@ def comment_token @i += comment.length end + # Record tokens for indentation differing from the previous line. + def indent_token + return false unless indent = @chunk[MULTI_DENT, 1] + @line += indent.scan(MULTILINER).size + @i += indent.size + return suppress_newlines(indent) if last_value.to_s.match(NO_NEWLINE) && last_value != "=>" + size = indent.scan(LAST_DENT).last.last.length + return newline_token(indent) if size == @indent + if size > @indent + token(:INDENT, size - @indent) + @indents << (size - @indent) + else + outdent_token(@indent - size) + end + @indent = size + end + + # Record an oudent token or tokens, if we're moving back inwards past + # multiple recorded indents. + def outdent_token(move_out) + while move_out > 0 && !@indents.empty? + last_indent = @indents.pop + token(:OUTDENT, last_indent) + move_out -= last_indent + end + token("\n", "\n") + end + # Matches and consumes non-meaningful whitespace. def whitespace_token return false unless whitespace = @chunk[WHITESPACE, 1] @i += whitespace.length end + # Multiple newlines get merged together. + # Use a trailing \ to escape newlines. + def newline_token(newlines) + token("\n", "\n") unless last_value == "\n" + true + end + + # Tokens to explicitly escape newlines are removed once their job is done. + def suppress_newlines(newlines) + @tokens.pop if last_value == "\\" + true + end + # We treat all other single characters as a token. Eg.: ( ) , . ! # Multi-character operators are also literal tokens, so that Racc can assign - # the proper order of operations. Multiple newlines get merged together. - # Use a trailing \ to escape newlines. + # the proper order of operations. def literal_token - value = @chunk[NEWLINE, 1] - if value - @line += value.length - token("\n", "\n") unless ["\n", "\\"].include?(last_value) - @tokens.pop if last_value == "\\" - return @i += value.length - end value = @chunk[OPERATOR, 1] tag_parameters if value && value.match(CODE) value ||= @chunk[0,1] - skip_following_newlines if EXP_START.include?(value) - remove_leading_newlines if EXP_END.include?(value) - tag = ASSIGN.include?(value) ? :ASSIGN : value + tag = value.match(ASSIGNMENT) ? :ASSIGN : value token(tag, value) @i += value.length end + # Helpers ========================================================== + # Add a token to the results, taking note of the line number, and # immediately-preceding comment. def token(tag, value) @tokens << [tag, Value.new(value, @line)] end - # Peek at the previous token. + # Peek at the previous token's value. def last_value @tokens.last && @tokens.last[1] end + # Peek at the previous token's tag. + def last_tag + @tokens.last && @tokens.last[0] + end + # A source of ambiguity in our grammar was parameter lists in function # definitions (as opposed to argument lists in function calls). Tag - # parameter identifiers in order to avoid this. + # parameter identifiers in order to avoid this. Also, parameter lists can + # make use of splats. def tag_parameters - index = 0 + i = 0 loop do - tok = @tokens[index -= 1] + i -= 1 + tok = @tokens[i] return if !tok next if tok[0] == ',' + next tok[0] = :PARAM_SPLAT if tok[0] == '*' return if tok[0] != :IDENTIFIER tok[0] = :PARAM end end - # Consume and ignore newlines immediately after this point. - def skip_following_newlines - newlines = @code[(@i+1)..-1][NEWLINE, 1] - if newlines - @line += newlines.length - @i += newlines.length - end - end - - # Discard newlines immediately before this point. - def remove_leading_newlines - @tokens.pop if last_value == "\n" + # Close up all remaining open blocks. IF the first token is an indent, + # axe it. + def close_indentation + outdent_token(@indent) end end - end \ No newline at end of file diff --git a/lib/coffee_script/narwhal/coffee-script.coffee b/lib/coffee_script/narwhal/coffee-script.coffee index 2a4d8f58f7..d687c42b32 100644 --- a/lib/coffee_script/narwhal/coffee-script.coffee +++ b/lib/coffee_script/narwhal/coffee-script.coffee @@ -15,15 +15,16 @@ coffeePath: File.path(module.path).dirname().dirname().dirname().dirname().dirna checkForErrors: coffeeProcess => return true if coffeeProcess.wait() is 0 system.stderr.print(coffeeProcess.stderr.read()) - throw new Error("CoffeeScript compile error"). + throw new Error("CoffeeScript compile error") # Run a simple REPL, round-tripping to the CoffeeScript compiler for every # command. exports.run: args => - args.shift() if args.length - exports.evalCS(File.read(path)) for path in args. - return true. + for path, i in args + exports.evalCS(File.read(path)) + delete args[i] + return true while true try @@ -31,31 +32,31 @@ exports.run: args => result: exports.evalCS(Readline.readline()) print(result) if result isnt undefined catch e - print(e)... + print(e) # Compile a given CoffeeScript file into JavaScript. exports.compileFile: path => coffee: OS.popen([coffeePath, "--print", "--no-wrap", path]) checkForErrors(coffee) - coffee.stdout.read(). + coffee.stdout.read() # Compile a string of CoffeeScript into JavaScript. exports.compile: source => coffee: OS.popen([coffeePath, "--eval", "--no-wrap"]) coffee.stdin.write(source).flush().close() checkForErrors(coffee) - coffee.stdout.read(). + coffee.stdout.read() # Evaluating a string of CoffeeScript first compiles it externally. exports.evalCS: source => - eval(exports.compile(source)). + eval(exports.compile(source)) # Make a factory for the CoffeeScript environment. exports.makeNarwhalFactory: path => - code: exports.compileFile(path) - factoryText: "function(require,exports,module,system,print){ 1 + 1 /**/\n}" - if system.engine is "rhino" - Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null) - else - # eval requires parenthesis, but parenthesis break compileFunction. - eval("(" + factoryText + ")").. + code: exports.compileFile(path) + factoryText: "function(require,exports,module,system,print){" + code + "/**/\n}" + if system.engine is "rhino" + Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null) + else + # eval requires parentheses, but parentheses break compileFunction. + eval("(" + factoryText + ")") diff --git a/lib/coffee_script/narwhal/js/launcher.js b/lib/coffee_script/narwhal/js/launcher.js deleted file mode 100644 index c8442a18d9..0000000000 --- a/lib/coffee_script/narwhal/js/launcher.js +++ /dev/null @@ -1,3 +0,0 @@ -(function(){ - require("./coffee-script").run(system.args); -})(); \ No newline at end of file diff --git a/lib/coffee_script/narwhal/launcher.coffee b/lib/coffee_script/narwhal/launcher.coffee deleted file mode 100644 index ec83edef9b..0000000000 --- a/lib/coffee_script/narwhal/launcher.coffee +++ /dev/null @@ -1 +0,0 @@ -require("./coffee-script").run(system.args) \ No newline at end of file diff --git a/lib/coffee_script/narwhal/js/coffee-script.js b/lib/coffee_script/narwhal/lib/coffee-script.js similarity index 71% rename from lib/coffee_script/narwhal/js/coffee-script.js rename to lib/coffee_script/narwhal/lib/coffee-script.js index dc283606e3..99a2c40c12 100644 --- a/lib/coffee_script/narwhal/js/coffee-script.js +++ b/lib/coffee_script/narwhal/lib/coffee-script.js @@ -1,14 +1,16 @@ (function(){ var File, OS, Readline, checkForErrors, coffeePath; - // This (javascript) file is generated from lib/coffee_script/narwhal/coffee-script.coffee Executes the `coffee` Ruby program to convert from CoffeeScript - // to Javascript. Eventually this will hopefully happen entirely within JS. Require external dependencies. + // This (javascript) file is generated from lib/coffee_script/narwhal/coffee-script.coffee + // Executes the `coffee` Ruby program to convert from CoffeeScript + // to Javascript. Eventually this will hopefully happen entirely within JS. + // Require external dependencies. OS = require('os'); File = require('file'); Readline = require('readline'); // The path to the CoffeeScript Compiler. coffeePath = File.path(module.path).dirname().dirname().dirname().dirname().dirname().join('bin', 'coffee'); // Our general-purpose error handler. - checkForErrors = function(coffeeProcess) { + checkForErrors = function checkForErrors(coffeeProcess) { if (coffeeProcess.wait() === 0) { return true; } @@ -17,17 +19,20 @@ }; // Run a simple REPL, round-tripping to the CoffeeScript compiler for every // command. - exports.run = function(args) { - var __a, __b, __c, __d, path, result; - args.shift(); + exports.run = function run(args) { + var __a, __b, __c, i, path, result; if (args.length) { __a = args; - __d = []; - for (__b=0, __c=__a.length; __b<__c; __b++) { - path = __a[__b]; - __d[__b] = exports.evalCS(File.read(path)); + __b = []; + for (i in __a) { + if (__a.hasOwnProperty(i)) { + path = __a[i]; + exports.evalCS(File.read(path)); + __c = delete args[i]; + __b.push(__c); + } } - __d; + __b; return true; } while (true) { @@ -43,14 +48,14 @@ } }; // Compile a given CoffeeScript file into JavaScript. - exports.compileFile = function(path) { + exports.compileFile = function compileFile(path) { var coffee; coffee = OS.popen([coffeePath, "--print", "--no-wrap", path]); checkForErrors(coffee); return coffee.stdout.read(); }; // Compile a string of CoffeeScript into JavaScript. - exports.compile = function(source) { + exports.compile = function compile(source) { var coffee; coffee = OS.popen([coffeePath, "--eval", "--no-wrap"]); coffee.stdin.write(source).flush().close(); @@ -58,18 +63,18 @@ return coffee.stdout.read(); }; // Evaluating a string of CoffeeScript first compiles it externally. - exports.evalCS = function(source) { + exports.evalCS = function evalCS(source) { return eval(exports.compile(source)); }; // Make a factory for the CoffeeScript environment. - exports.makeNarwhalFactory = function(path) { + exports.makeNarwhalFactory = function makeNarwhalFactory(path) { var code, factoryText; code = exports.compileFile(path); - factoryText = "function(require,exports,module,system,print){ 1 + 1 /**/\n}"; + factoryText = "function(require,exports,module,system,print){" + code + "/**/\n}"; if (system.engine === "rhino") { return Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null); } else { - // eval requires parenthesis, but parenthesis break compileFunction. + // eval requires parentheses, but parentheses break compileFunction. return eval("(" + factoryText + ")"); } }; diff --git a/lib/coffee_script/narwhal/js/loader.js b/lib/coffee_script/narwhal/lib/coffee-script/loader.js similarity index 64% rename from lib/coffee_script/narwhal/js/loader.js rename to lib/coffee_script/narwhal/lib/coffee-script/loader.js index cf4c1ed43a..24b7ef27bb 100644 --- a/lib/coffee_script/narwhal/js/loader.js +++ b/lib/coffee_script/narwhal/lib/coffee-script/loader.js @@ -6,12 +6,14 @@ }; loader = { // Reload the coffee-script environment from source. - reload: function(topId, path) { - coffeescript = coffeescript || require('./coffee-script'); - return (factories[topId] = coffeescript.makeNarwhalFactory(path)); + reload: function reload(topId, path) { + coffeescript = coffeescript || require('coffee-script'); + return (factories[topId] = function() { + return coffeescript.makeNarwhalFactory(path); + }); }, // Ensure that the coffee-script environment is loaded. - load: function(topId, path) { + load: function load(topId, path) { return factories[topId] = factories[topId] || this.reload(topId, path); } }; diff --git a/lib/coffee_script/narwhal/loader.coffee b/lib/coffee_script/narwhal/loader.coffee index 9797408afd..ea6e2a0edc 100644 --- a/lib/coffee_script/narwhal/loader.coffee +++ b/lib/coffee_script/narwhal/loader.coffee @@ -7,12 +7,12 @@ loader: { # Reload the coffee-script environment from source. reload: topId, path => - coffeescript ||= require('./coffee-script') - factories[topId]: coffeescript.makeNarwhalFactory(path). + coffeescript ||= require('coffee-script') + factories[topId]: => coffeescript.makeNarwhalFactory(path) # Ensure that the coffee-script environment is loaded. load: topId, path => - factories[topId] ||= this.reload(topId, path). + factories[topId] ||= this.reload(topId, path) } diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 7730ed7444..7ad9418fea 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -11,17 +11,11 @@ def self.statement class_eval "def statement?; true; end" end - # Tag this node as having a custom return, meaning that instead of returning - # it from the outside, you ask it to return itself, and it obliges. - def self.custom_return - class_eval "def custom_return?; true; end" - end - - # Tag this node as having a custom assignment, meaning that instead of - # assigning it to a variable name from the outside, you pass it the variable - # name and let it take care of it. - def self.custom_assign - class_eval "def custom_assign?; true; end" + # Tag this node as a statement that cannot be transformed into an expression. + # (break, continue, etc.) It doesn't make sense to try to transform it. + def self.statement_only + statement + class_eval "def statement_only?; true; end" end def write(code) @@ -29,16 +23,27 @@ def write(code) code end + # This is extremely important -- we convert JS statements into expressions + # by wrapping them in a closure, only if it's possible, and we're not at + # the top level of a block (which would be unnecessary), and we haven't + # already been asked to return the result. def compile(o={}) @options = o.dup + top = self.is_a?(ForNode) ? @options[:top] : @options.delete(:top) + closure = statement? && !statement_only? && !top && !@options[:return] + closure ? compile_closure(@options) : compile_node(@options) + end + + def compile_closure(o={}) + indent = o[:indent] + o[:indent] += TAB + "(function() {\n#{compile_node(o.merge(:return => true))}\n#{indent}})()" end # Default implementations of the common node methods. - def unwrap; self; end - def line_ending; ';'; end - def statement?; false; end - def custom_return?; false; end - def custom_assign?; false; end + def unwrap; self; end + def statement?; false; end + def statement_only?; false; end end # A collection of nodes, each one representing an expression. @@ -49,12 +54,13 @@ class Expressions < Node STRIP_TRAILING_WHITESPACE = /\s+$/ # Wrap up a node as an Expressions, unless it already is. - def self.wrap(node) - node.is_a?(Expressions) ? node : Expressions.new([node]) + def self.wrap(*nodes) + return nodes[0] if nodes.length == 1 && nodes[0].is_a?(Expressions) + Expressions.new(*nodes) end - def initialize(nodes) - @expressions = nodes + def initialize(*nodes) + @expressions = nodes.flatten end # Tack an expression onto the end of this node. @@ -63,6 +69,11 @@ def <<(node) self end + def unshift(node) + @expressions.unshift(node) + self + end + # If this Expressions consists of a single node, pull it back out. def unwrap @expressions.length == 1 ? @expressions.first : self @@ -74,47 +85,48 @@ def last?(node) node == @expressions[@last_index] end - # If this is the top-level Expressions, wrap everything in a safety closure. - def root_compile(o={}) - indent = o[:no_wrap] ? '' : TAB - code = compile(o.merge(:indent => indent, :scope => Scope.new), o[:no_wrap] ? nil : :code) - code.gsub!(STRIP_TRAILING_WHITESPACE, '') - o[:no_wrap] ? code : "(function(){\n#{code}\n})();" + def compile(o={}) + o[:scope] ? super(o) : compile_root(o) end - # The extra fancy is to handle pushing down returns and assignments - # recursively to the final lines of inner statements. - # Variables first defined within the Expressions body have their - # declarations pushed up to the top scope. - def compile(options={}, parent=nil) - return root_compile(options) unless options[:scope] + # The extra fancy is to handle pushing down returns to the final lines of + # inner statements. Variables first defined within the Expressions body + # have their declarations pushed up top of the closest scope. + def compile_node(options={}) compiled = @expressions.map do |node| - o = super(options) - if last?(node) && (o[:return] || o[:assign]) - if o[:return] - if node.statement? || node.custom_return? - "#{o[:indent]}#{node.compile(o)}#{node.line_ending}" - else - o.delete(:return) - "#{o[:indent]}return #{node.compile(o)}#{node.line_ending}" - end - elsif o[:assign] - if node.statement? || node.custom_assign? - "#{o[:indent]}#{node.compile(o)}#{node.line_ending}" - else - "#{o[:indent]}#{AssignNode.new(o[:assign], node).compile(o)};" - end + o = options.dup + returns = o.delete(:return) + if last?(node) && returns && !node.statement_only? + if node.statement? + node.compile(o.merge(:return => true)) + else + "#{o[:indent]}return #{node.compile(o)};" end else - o.delete(:return) and o.delete(:assign) - "#{o[:indent]}#{node.compile(o)}#{node.line_ending}" + ending = node.statement? ? '' : ';' + indent = node.statement? ? '' : o[:indent] + "#{indent}#{node.compile(o.merge(:top => true))}#{ending}" end end - scope = options[:scope] - declarations = scope.any_declared? && parent == :code ? "#{options[:indent]}var #{scope.declared_variables.join(', ')};\n" : '' - code = declarations + compiled.join("\n") - write(code) + write(compiled.join("\n")) + end + + # If this is the top-level Expressions, wrap everything in a safety closure. + def compile_root(o={}) + indent = o[:no_wrap] ? '' : TAB + o.merge!(:indent => indent, :scope => Scope.new(nil, self)) + code = o[:no_wrap] ? compile_node(o) : compile_with_declarations(o) + code.gsub!(STRIP_TRAILING_WHITESPACE, '') + o[:no_wrap] ? code : "(function(){\n#{code}\n})();" + end + + def compile_with_declarations(o={}) + code = compile_node(o) + decls = '' + decls = "#{o[:indent]}var #{o[:scope].declared_variables.join(', ')};\n" if o[:scope].declarations?(self) + decls + code end + end # Literals are static values that have a Ruby representation, eg.: a string, a number, @@ -131,21 +143,18 @@ def initialize(value) def statement? STATEMENTS.include?(@value.to_s) end + alias_method :statement_only?, :statement? - def line_ending - @value.to_s[-1..-1] == ';' ? '' : ';' - end - - def compile(o={}) - o = super(o) - write(@value.to_s) + def compile_node(o) + indent = statement? ? o[:indent] : '' + ending = statement? ? ';' : '' + write(indent + @value.to_s + ending) end end # Try to return your expression, or tell it to return itself. class ReturnNode < Node - statement - custom_return + statement_only attr_reader :expression @@ -153,32 +162,23 @@ def initialize(expression) @expression = expression end - def line_ending - @expression.custom_return? ? '' : ';' - end - - def compile(o={}) - o = super(o) - return write(@expression.compile(o.merge(:return => true))) if @expression.custom_return? + def compile_node(o) + return write(@expression.compile(o.merge(:return => true))) if @expression.statement? compiled = @expression.compile(o) - write(@expression.statement? ? "#{compiled}\n#{indent}return null" : "return #{compiled}") + write(@expression.statement? ? "#{compiled}\n#{o[:indent]}return null;" : "#{o[:indent]}return #{compiled};") end end # Pass through CoffeeScript comments into JavaScript comments at the # same position. class CommentNode < Node - statement + statement_only def initialize(lines) @lines = lines.value end - def line_ending - '' - end - - def compile(o={}) + def compile_node(o={}) delimiter = "\n#{o[:indent]}//" comment = "#{delimiter}#{@lines.join(delimiter)}" write(comment) @@ -189,8 +189,6 @@ def compile(o={}) # Node for a function invocation. Takes care of converting super() calls into # calls against the prototype's function of the same name. class CallNode < Node - LEADING_DOT = /\A\./ - attr_reader :variable, :arguments def initialize(variable, arguments=[]) @@ -206,42 +204,65 @@ def super? @variable == :super end - def compile(o={}) - o = super(o) + def prefix + @new ? "new " : '' + end + + def splat? + @arguments.any? {|a| a.is_a?(ArgSplatNode) } + end + + def <<(argument) + @arguments << argument + end + + def compile_node(o) + return write(compile_splat(o)) if splat? args = @arguments.map{|a| a.compile(o) }.join(', ') return write(compile_super(args, o)) if super? - prefix = @new ? "new " : '' write("#{prefix}#{@variable.compile(o)}(#{args})") end def compile_super(args, o) - methname = o[:last_assign].sub(LEADING_DOT, '') + methname = o[:last_assign] arg_part = args.empty? ? '' : ", #{args}" "#{o[:proto_assign]}.__superClass__.#{methname}.call(this#{arg_part})" end + + def compile_splat(o) + meth = @variable.compile(o) + obj = @variable.source || 'this' + args = @arguments.map do |arg| + code = arg.compile(o) + code = arg.is_a?(ArgSplatNode) ? code : "[#{code}]" + arg.equal?(@arguments.first) ? code : ".concat(#{code})" + end + "#{prefix}#{meth}.apply(#{obj}, #{args.join('')})" + end end # Node to extend an object's prototype with an ancestor object. # After goog.inherits from the Closure Library. class ExtendsNode < Node + statement attr_reader :sub_object, :super_object def initialize(sub_object, super_object) @sub_object, @super_object = sub_object, super_object end - def compile(o={}) + def compile_node(o={}) sub, sup = @sub_object.compile(o), @super_object.compile(o) - "#{sub}.__superClass__ = #{sup}.prototype;\n#{o[:indent]}" + + "#{o[:indent]}#{sub}.__superClass__ = #{sup}.prototype;\n#{o[:indent]}" + "#{sub}.prototype = new #{sup}();\n#{o[:indent]}" + - "#{sub}.prototype.constructor = #{sub}" + "#{sub}.prototype.constructor = #{sub};" end end # A value, indexed or dotted into, or vanilla. class ValueNode < Node - attr_reader :literal, :properties, :last + attr_reader :literal, :properties, :last, :source def initialize(literal, properties=[]) @literal, @properties = literal, properties @@ -260,20 +281,14 @@ def statement? @literal.is_a?(Node) && @literal.statement? && !properties? end - def custom_assign? - @literal.is_a?(Node) && @literal.custom_assign? && !properties? - end - - def custom_return? - @literal.is_a?(Node) && @literal.custom_return? && !properties? - end - - def compile(o={}) - o = super(o) - parts = [@literal, @properties].flatten.map do |val| + def compile_node(o) + only = o.delete(:only_first) + props = only ? @properties[0...-1] : @properties + parts = [@literal, props].flatten.map do |val| val.respond_to?(:compile) ? val.compile(o) : val.to_s end @last = parts.last + @source = parts.length > 1 ? parts[0...-1].join('') : nil write(parts.join('')) end end @@ -286,8 +301,7 @@ def initialize(name) @name = name end - def compile(o={}) - o = super(o) + def compile_node(o) write(".#{@name}") end end @@ -300,15 +314,14 @@ def initialize(index) @index = index end - def compile(o={}) - o = super(o) + def compile_node(o) write("[#{@index.compile(o)}]") 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 + class RangeNode < Node attr_reader :from, :to def initialize(from, to, exclusive=false) @@ -327,12 +340,21 @@ def greater_operator @exclusive ? '>' : '>=' end - def compile(o, fv, tv) - fvv, tvv = @from.compile(o), @to.compile(o) - vars = "#{fv}=#{fvv}, #{tv}=#{tvv}" - compare = "(#{fvv} <= #{tvv} ? #{fv} #{less_operator} #{tv} : #{fv} #{greater_operator} #{tv})" - incr = "(#{fvv} <= #{tvv} ? #{fv} += 1 : #{fv} -= 1)" - "#{vars}; #{compare}; #{incr}" + def compile_variables(o) + idt = o[:indent] + @from_var, @to_var = o[:scope].free_variable, o[:scope].free_variable + from_val, to_val = @from.compile(o), @to.compile(o) + write("#{idt}#{@from_var} = #{from_val};\n#{idt}#{@to_var} = #{to_val};\n#{idt}") + end + + def compile_node(o) + idx, step = o.delete(:index), o.delete(:step) + raise SyntaxError, "unexpected range literal" unless idx + vars = "#{idx}=#{@from_var}" + step = step ? step.compile(o) : '1' + compare = "(#{@from_var} <= #{@to_var} ? #{idx} #{less_operator} #{@to_var} : #{idx} #{greater_operator} #{@to_var})" + incr = "(#{@from_var} <= #{@to_var} ? #{idx} += #{step} : #{idx} -= #{step})" + write("#{vars}; #{compare}; #{incr}") end end @@ -347,8 +369,7 @@ def initialize(range) @range = range end - def compile(o={}) - o = super(o) + def compile_node(o) from = @range.from.compile(o) to = @range.to.compile(o) plus_part = @range.exclusive? ? '' : ' + 1' @@ -359,8 +380,7 @@ def compile(o={}) # Setting the value of a local variable, or the value of an object property. class AssignNode < Node PROTO_ASSIGN = /\A(\S+)\.prototype/ - - custom_return + LEADING_DOT = /\A\./ attr_reader :variable, :value, :context @@ -368,21 +388,26 @@ def initialize(variable, value, context=nil) @variable, @value, @context = variable, value, context end - def line_ending - @value.custom_assign? ? '' : ';' - end - - def compile(o={}) - o = super(o) + def compile_node(o) + return compile_splice(o) if @variable.properties.last.is_a?(SliceNode) name = @variable.compile(o) - last = @variable.last.to_s + last = @variable.last.to_s.sub(LEADING_DOT, '') proto = name[PROTO_ASSIGN, 1] - o = o.merge(:assign => @variable, :last_assign => last, :proto_assign => proto) + o = o.merge(:last_assign => last, :proto_assign => proto) + o[:immediate_assign] = last if @value.is_a?(CodeNode) && last.match(Lexer::IDENTIFIER) return write("#{name}: #{@value.compile(o)}") if @context == :object o[:scope].find(name) unless @variable.properties? - return write(@value.compile(o)) if @value.custom_assign? val = "#{name} = #{@value.compile(o)}" - write(o[:return] && !@value.custom_return? ? "return (#{val})" : val) + write(o[:return] ? "#{o[:indent]}return (#{val})" : val) + end + + def compile_splice(o) + var = @variable.compile(o.merge(:only_first => true)) + range = @variable.properties.last.range + plus = range.exclusive? ? '' : ' + 1' + from = range.from.compile(o) + to = "#{range.to.compile(o)} - #{from}#{plus}" + write("#{var}.splice.apply(#{var}, [#{from}, #{to}].concat(#{@value.compile(o)}))") end end @@ -390,31 +415,30 @@ def compile(o={}) # CoffeeScript operations into their JavaScript equivalents. class OpNode < Node CONVERSIONS = { - "==" => "===", - "!=" => "!==", - 'and' => '&&', - 'or' => '||', - 'is' => '===', - "isnt" => "!==", - 'not' => '!' + :== => "===", + :'!=' => "!==", + :and => '&&', + :or => '||', + :is => '===', + :isnt => "!==", + :not => '!' } - CONDITIONALS = ['||=', '&&='] - PREFIX_OPERATORS = ['typeof', 'delete'] + CONDITIONALS = [:'||=', :'&&='] + PREFIX_OPERATORS = [:typeof, :delete] attr_reader :operator, :first, :second def initialize(operator, first, second=nil, flip=false) @first, @second, @flip = first, second, flip - @operator = CONVERSIONS[operator] || operator + @operator = CONVERSIONS[operator.to_sym] || operator end def unary? @second.nil? end - def compile(o={}) - o = super(o) - return write(compile_conditional(o)) if CONDITIONALS.include?(@operator) + def compile_node(o) + return write(compile_conditional(o)) if CONDITIONALS.include?(@operator.to_sym) return write(compile_unary(o)) if unary? write("#{@first.compile(o)} #{@operator} #{@second.compile(o)}") end @@ -426,7 +450,7 @@ def compile_conditional(o) end def compile_unary(o) - space = PREFIX_OPERATORS.include?(@operator.to_s) ? ' ' : '' + space = PREFIX_OPERATORS.include?(@operator.to_sym) ? ' ' : '' parts = [@operator.to_s, space, @first.compile(o)] parts.reverse! if @flip parts.join('') @@ -442,18 +466,53 @@ def initialize(params, body) @body = body end - def compile(o={}) - o = super(o) - o[:scope] = Scope.new(o[:scope]) - o[:return] = true - indent = o[:indent] - o[:indent] += TAB - o.delete(:assign) + def compile_node(o) + shared_scope = o.delete(:shared_scope) + indent = o[:indent] + o[:scope] = shared_scope || Scope.new(o[:scope], @body) + o[:return] = true + o[:top] = true + o[:indent] += TAB o.delete(:no_wrap) + name = o.delete(:immediate_assign) + if @params.last.is_a?(ParamSplatNode) + splat = @params.pop + splat.index = @params.length + @body.unshift(splat) + end @params.each {|id| o[:scope].parameter(id.to_s) } - code = @body.compile(o, :code) - write("function(#{@params.join(', ')}) {\n#{code}\n#{indent}}") + code = @body.compile_with_declarations(o) + name_part = name ? " #{name}" : '' + write("function#{name_part}(#{@params.join(', ')}) {\n#{code}\n#{indent}}") + end + end + + # A parameter splat in a function definition. + class ParamSplatNode < Node + attr_accessor :index + attr_reader :name + + def initialize(name) + @name = name + end + + def compile_node(o={}) + o[:scope].find(@name) + write("#{@name} = Array.prototype.slice.call(arguments, #{@index})") + end + end + + class ArgSplatNode < Node + attr_reader :value + + def initialize(value) + @value = value + end + + def compile_node(o={}) + write(@value.compile(o)) end + end # An object literal. @@ -464,13 +523,20 @@ def initialize(properties = []) @properties = properties end - def compile(o={}) - o = super(o) + # All the mucking about with commas is to make sure that CommentNodes and + # AssignNodes get interleaved correctly, with no trailing commas or + # commas affixed to comments. TODO: Extract this and add it to ArrayNode. + def compile_node(o) indent = o[:indent] o[:indent] += TAB - props = @properties.map { |prop| - joiner = prop == @properties.last ? '' : prop.is_a?(CommentNode) ? "\n" : ",\n" - o[:indent] + prop.compile(o) + joiner + joins = Hash.new("\n") + non_comments = @properties.select {|p| !p.is_a?(CommentNode) } + non_comments.each {|p| joins[p] = p == non_comments.last ? "\n" : ",\n" } + props = @properties.map { |prop| + join = joins[prop] + join = '' if prop == @properties.last + idt = prop.is_a?(CommentNode) ? '' : o[:indent] + "#{idt}#{prop.compile(o)}#{join}" }.join('') write("{\n#{props}\n#{indent}}") end @@ -484,13 +550,15 @@ def initialize(objects=[]) @objects = objects end - def compile(o={}) - o = super(o) + def compile_node(o) + indent = o[:indent] + o[:indent] += TAB objects = @objects.map { |obj| - joiner = obj.is_a?(CommentNode) ? "\n#{o[:indent] + TAB}" : obj == @objects.last ? '' : ', ' - obj.compile(o.merge(:indent => o[:indent] + TAB)) + joiner + code = obj.compile(o) + obj.is_a?(CommentNode) ? "\n#{code}\n#{o[:indent]}" : + obj == @objects.last ? code : "#{code}, " }.join('') - ending = objects.include?("\n") ? "\n#{o[:indent]}]" : ']' + ending = objects.include?("\n") ? "\n#{indent}]" : ']' write("[#{objects}#{ending}") end end @@ -506,16 +574,14 @@ def initialize(condition, body) @condition, @body = condition, body end - def line_ending - '' - end - - def compile(o={}) - o = super(o) - o.delete(:return) - indent = o[:indent] + TAB - cond = @condition.compile(o) - write("while (#{cond}) {\n#{@body.compile(o.merge(:indent => indent))}\n#{o[:indent]}}") + def compile_node(o) + returns = o.delete(:return) + indent = o[:indent] + o[:indent] += TAB + o[:top] = true + cond = @condition.compile(o) + post = returns ? "\n#{indent}return null;" : '' + write("#{indent}while (#{cond}) {\n#{@body.compile(o)}\n#{indent}}#{post}") end end @@ -525,74 +591,70 @@ def compile(o={}) # the current index of the loop as a second parameter. class ForNode < Node statement - custom_return - custom_assign - - attr_reader :body, :source, :name, :filter, :index - def initialize(body, source, name, filter, index=nil) - @body, @source, @name, @filter, @index = body, source, name, filter, index - end + attr_reader :body, :source, :name, :index, :filter, :step - def line_ending - '' + def initialize(body, source, name, index=nil) + @body, @name, @index = body, name, index + @source = source[:source] + @filter = source[:filter] + @step = source[:step] end - def compile(o={}) - o = super(o) + def compile_node(o) + top_level = o.delete(:top) && !o[:return] range = @source.is_a?(RangeNode) scope = o[:scope] name_found = scope.find(@name) index_found = @index && scope.find(@index) svar = scope.free_variable - ivar = range ? name : scope.free_variable - lvar = scope.free_variable - rvar = scope.free_variable - index_name = @index ? @index : nil + ivar = range ? name : @index ? @index : scope.free_variable + rvar = scope.free_variable unless top_level + tvar = scope.free_variable if range - source_part = '' - var_part = '' - index_part = '' + body_dent = o[:indent] + TAB + var_part, pre_cond, post_cond = '', '', '' index_var = scope.free_variable - for_part = "#{index_var}=0, #{@source.compile(o, ivar, lvar)}, #{index_var}++" + source_part = @source.compile_variables(o) + for_part = "#{index_var}=0, #{@source.compile(o.merge(:index => ivar, :step => @step))}, #{index_var}++" else index_var = nil - source_part = "#{svar} = #{@source.compile(o)};\n#{o[:indent]}" - for_part = "#{ivar}=0, #{lvar}=#{svar}.length; #{ivar}<#{lvar}; #{ivar}++" - var_part = "\n#{o[:indent] + TAB}#{@name} = #{svar}[#{ivar}];" - index_part = @index ? "\n#{o[:indent] + TAB}#{index_name} = #{ivar};" : '' + body_dent = o[:indent] + TAB + TAB + source_part = "#{o[:indent]}#{svar} = #{@source.compile(o)};\n#{o[:indent]}" + for_part = "#{ivar} in #{svar}" + pre_cond = "\n#{o[:indent] + TAB}if (#{svar}.hasOwnProperty(#{ivar})) {" + var_part = "\n#{body_dent}#{@name} = #{svar}[#{ivar}];" + post_cond = "\n#{o[:indent] + TAB}}" end body = @body - suffix = ';' - set_result = "#{rvar} = [];\n#{o[:indent]}" - save_result = "#{rvar}[#{index_var || ivar}] = " - return_result = rvar - - if o[:return] || o[:assign] - return_result = "#{o[:assign].compile(o)} = #{return_result}" if o[:assign] + set_result = rvar ? "#{rvar} = [];\n#{o[:indent]}" : '' + return_result = rvar || '' + temp_var = ValueNode.new(LiteralNode.new(tvar)) + if top_level + body = Expressions.wrap(body) + else + body = Expressions.wrap( + AssignNode.new(temp_var, @body.unwrap), + CallNode.new(ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [temp_var]) + ) + end + if o[:return] return_result = "return #{return_result}" if o[:return] - if @filter - body = CallNode.new(ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [@body]) - body = IfNode.new(@filter, body, nil, :statement => true) - save_result = '' - suffix = '' - end + o.delete(:return) + body = IfNode.new(@filter, body, nil, :statement => true) if @filter elsif @filter - body = IfNode.new(@filter, @body) + body = Expressions.wrap(IfNode.new(@filter, @body)) end - return_result = "\n#{o[:indent]}#{return_result};" - indent = o[:indent] + TAB - body = body.compile(o.merge(:indent => indent)) - write("#{source_part}#{set_result}for (#{for_part}) {#{var_part}#{index_part}\n#{indent}#{save_result}#{body}#{suffix}\n#{o[:indent]}}#{return_result}") + return_result = "\n#{o[:indent]}#{return_result};" unless top_level + body = body.compile(o.merge(:indent => body_dent, :top => true)) + write("#{source_part}#{set_result}for (#{for_part}) {#{pre_cond}#{var_part}\n#{body}#{post_cond}\n#{o[:indent]}}#{return_result}") end end # A try/catch/finally block. class TryNode < Node statement - custom_return - custom_assign attr_reader :try, :error, :recovery, :finally @@ -600,24 +662,20 @@ def initialize(try, error, recovery, finally=nil) @try, @error, @recovery, @finally = try, error, recovery, finally end - def line_ending - '' - end - - def compile(o={}) - o = super(o) + def compile_node(o) indent = o[:indent] o[:indent] += TAB + o[:top] = true error_part = @error ? " (#{@error}) " : ' ' catch_part = @recovery && " catch#{error_part}{\n#{@recovery.compile(o)}\n#{indent}}" - finally_part = @finally && " finally {\n#{@finally.compile(o.merge(:assign => nil, :return => nil))}\n#{indent}}" - write("try {\n#{@try.compile(o)}\n#{indent}}#{catch_part}#{finally_part}") + finally_part = @finally && " finally {\n#{@finally.compile(o.merge(:return => nil))}\n#{indent}}" + write("#{indent}try {\n#{@try.compile(o)}\n#{indent}}#{catch_part}#{finally_part}") end end # Throw an exception. class ThrowNode < Node - statement + statement_only attr_reader :expression @@ -625,9 +683,22 @@ def initialize(expression) @expression = expression end - def compile(o={}) - o = super(o) - write("throw #{@expression.compile(o)}") + def compile_node(o) + write("#{o[:indent]}throw #{@expression.compile(o)};") + end + end + + # Check an expression for existence (meaning not null or undefined). + class ExistenceNode < Node + attr_reader :expression + + def initialize(expression) + @expression = expression + end + + def compile_node(o) + val = @expression.compile(o) + write("(typeof #{val} !== \"undefined\" && #{val} !== null)") end end @@ -637,25 +708,12 @@ def compile(o={}) class ParentheticalNode < Node attr_reader :expressions - def initialize(expressions) + def initialize(expressions, line=nil) @expressions = expressions.unwrap + @line = line end - def statement? - @expressions.unwrap.statement? - end - - def custom_assign? - @expressions.custom_assign? - end - - def custom_return? - @expressions.custom_return? - end - - def compile(o={}) - raise SyntaxError, "parentheses can't be wrapped around a statement" if statement? - o = super(o) + def compile_node(o) compiled = @expressions.compile(o) compiled = compiled[0...-1] if compiled[-1..-1] == ';' write("(#{compiled})") @@ -683,6 +741,11 @@ def <<(else_body) self end + def force_statement + @tags[:statement] = true + self + end + # Rewrite a chain of IfNodes with their switch condition for equality. def rewrite_condition(expression) @condition = OpNode.new("is", expression, @condition) @@ -691,8 +754,8 @@ def rewrite_condition(expression) end # Rewrite a chain of IfNodes to add a default case as the final else. - def add_else(expressions) - chain? ? @else_body.add_else(expressions) : @else_body = expressions + def add_else(exprs) + chain? ? @else_body.add_else(exprs) : @else_body = (exprs && exprs.unwrap) self end @@ -707,20 +770,7 @@ def statement? @is_statement ||= !!(@tags[:statement] || @body.statement? || (@else_body && @else_body.statement?)) end - def custom_return? - statement? - end - - def custom_assign? - statement? - end - - def line_ending - statement? ? '' : ';' - end - - def compile(o={}) - o = super(o) + def compile_node(o) write(statement? ? compile_statement(o) : compile_ternary(o)) end @@ -728,14 +778,16 @@ def compile(o={}) # force sub-else bodies into statement form. def compile_statement(o) indent = o[:indent] + child = o.delete(:chain_child) cond_o = o.dup - cond_o.delete(:assign) cond_o.delete(:return) o[:indent] += TAB - if_part = "if (#{@condition.compile(cond_o)}) {\n#{Expressions.wrap(@body).compile(o)}\n#{indent}}" + o[:top] = true + if_dent = child ? '' : indent + if_part = "#{if_dent}if (#{@condition.compile(cond_o)}) {\n#{Expressions.wrap(@body).compile(o)}\n#{indent}}" return if_part unless @else_body else_part = chain? ? - " else #{@else_body.compile(o.merge(:indent => indent))}" : + " else #{@else_body.compile(o.merge(:indent => indent, :chain_child => true))}" : " else {\n#{Expressions.wrap(@else_body).compile(o)}\n#{indent}}" if_part + else_part end diff --git a/lib/coffee_script/parse_error.rb b/lib/coffee_script/parse_error.rb index b9cc2e430b..3415ed1207 100644 --- a/lib/coffee_script/parse_error.rb +++ b/lib/coffee_script/parse_error.rb @@ -12,8 +12,9 @@ def initialize(token_id, value, stack) def message line = @value.respond_to?(:line) ? @value.line : "END" line_part = "line #{line}:" - id_part = @token_id != @value.inspect ? ", unexpected #{@token_id.downcase}" : "" - "#{line_part} syntax error for '#{@value.to_s}'#{id_part}" + id_part = @token_id != @value.inspect ? ", unexpected #{@token_id.to_s.downcase}" : "" + val_part = ['INDENT', 'OUTDENT'].include?(@token_id) ? '' : " for '#{@value.to_s}'" + "#{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 index 5b97e8b404..89b68891d9 100644 --- a/lib/coffee_script/parser.rb +++ b/lib/coffee_script/parser.rb @@ -10,7 +10,7 @@ module CoffeeScript class Parser < Racc::Parser -module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 400) +module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 421) # Lex and parse a CoffeeScript. def parse(code) # Uncomment the following line to enable grammar debugging, in combination @@ -34,258 +34,282 @@ def on_error(error_token_id, error_value, value_stack) ##### State transition tables begin ### clist = [ -'9,259,175,239,36,43,51,56,64,2,7,15,19,24,234,156,41,47,55,60,16,21', -'10,20,27,-152,-152,39,46,210,62,239,5,11,16,21,30,35,131,50,54,63,1', -'6,14,249,130,-152,-152,42,154,36,43,51,56,64,2,7,15,19,24,16,21,202', -'200,203,235,206,201,30,20,27,153,226,260,240,136,16,21,25,216,33,9,48', -'35,59,36,43,51,56,64,2,7,15,19,24,217,211,41,47,55,60,218,240,10,20', -'27,16,21,39,46,222,62,226,5,11,74,251,30,35,243,50,54,63,1,6,14,72,124', -'233,48,42,59,36,43,51,56,64,2,7,15,19,24,137,,267,,139,131,16,21,,20', -'27,16,21,130,,136,136,,25,,33,9,48,35,59,36,43,51,56,64,2,7,15,19,24', -',30,41,47,55,60,,265,10,20,27,16,21,39,46,,62,,5,11,16,21,30,35,,50', -'54,63,1,6,14,,124,,48,42,59,36,43,51,56,64,2,7,15,19,24,137,137,269', -'270,146,139,,16,21,20,27,131,89,93,,136,136,136,25,130,33,9,48,35,59', -'36,43,51,56,64,2,7,15,19,24,-152,-152,41,47,55,60,,30,10,20,27,79,80', -'39,46,,62,,5,11,89,93,30,35,247,50,54,63,1,6,14,,124,,48,42,59,36,43', -'51,56,64,2,7,15,19,24,137,137,137,261,139,146,139,248,,20,27,16,21,136', -',136,136,,25,,33,9,48,35,59,36,43,51,56,64,2,7,15,19,24,135,135,41,47', -'55,60,,240,10,20,27,16,21,39,46,,62,,5,11,89,93,30,35,,50,54,63,1,6', -'14,,124,,48,42,59,-152,-152,196,140,140,-152,-152,,137,,137,137,146', -',139,139,16,21,,194,16,21,,194,,215,16,21,25,236,33,9,48,,59,36,43,51', -'56,64,2,7,15,19,24,-152,-152,41,47,55,60,16,21,10,20,27,16,21,39,46', -',62,,5,11,-152,-152,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104,107', -'110,113,115,117,85,88,92,95,98,103,106,109,112,114,116,16,21,,194,,', -',,25,232,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10', -'20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99', -'104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114,116,16,21', -',194,,195,16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47', -'55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89', -'93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,89,93,96,99,104,107,110,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,,,,,42,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106', -'109,112,114,116,89,93,96,99,104,107,110,,25,,33,9,48,,59,36,43,51,56', -'64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,', -'50,54,63,1,6,14,,,,,42,89,93,96,99,104,107,110,113,115,117,85,88,92', -'95,98,103,106,109,112,114,116,89,93,96,99,104,,16,21,25,,33,9,48,,59', -'36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5', -'11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104,107,110,113,115,117', -'85,88,92,95,98,103,106,109,112,114,116,89,93,96,99,104,,16,21,25,,33', -'9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104,107,110,113', -'115,117,85,88,92,95,98,103,106,109,112,114,116,,,,,,,16,21,25,,33,9', -'48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104,107,110,113', -'115,117,85,88,92,95,98,103,106,109,112,114,116,,,,,,,16,21,25,,33,9', -'48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104,107,110,113', -'115,117,85,88,92,89,93,96,99,104,107,110,113,115,117,85,88,92,,,,25', -',33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,', -'39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104,107', -'110,113,115,117,85,88,92,89,93,96,99,104,107,110,113,115,117,85,88,92', -',,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20', -'27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93,96,99,104', -'107,110,113,115,117,89,93,96,99,104,107,110,113,115,117,89,93,96,99', -'104,107,110,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55', -'60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,89,93', -'96,99,104,107,110,113,115,117,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36', -'43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11', -',,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33', -'9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,', -',16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10', -'20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,', -',,,,,,,,,,,,,,,16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64', -'2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50', -'54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36', -'43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11', -',,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33', -'9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,', -',16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10', -'20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,', -',,,,,,,,,,,,,,,16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64', -'2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50', -'54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36', -'43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11', -',,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,16,21,25', -',33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,', -'39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,', -',10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,255,48,,59,36,43,51,56,64,2,7,15', -'19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1', -'6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,16,21,25,,33,9,48,,59,36,43,51', -'56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35', -',50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59', -'36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5', -'11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,', -'33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39', -'46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,', -',,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10', -'20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,', -',,,,,,,,,,,,,,,16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64', -'2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50', -'54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36', -'43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11', -',,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,16,21,25', -',33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,', -'39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,', -',,,,,,,16,21,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55', -'60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,', -',,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24', -',,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14', -',,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2', -'7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54', -'63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43', -'51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30', -'35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48', -',59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62', -',5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25', -',33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,', -'39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,', -',10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64', -'2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50', -'54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36', -'43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11', -',,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33', -'9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,', -',,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20', -'27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,', -',,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55', -'60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,', -',,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24', -',,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14', -',,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2', -'7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54', -'63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43', -'51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30', -'35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48', -',59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62', -',5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25', -',33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,', -'39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,', -',10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64', -'2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50', -'54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36', -'43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11', -',,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33', -'9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46', -',62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,', -',,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20', -'27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,', -',,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55', -'60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,', -',,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24', -',,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14', -',,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2', -'7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54', -'63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43', -'51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30', -'35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48', -',59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,,39,46,,62', -',5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25', -',33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,,,10,20,27,,', -'39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41,47,55,60,', -',10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42,,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19,24,,,41', -'47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6,14,,,,,42', -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,33,9,48,,59,36,43,51,56,64,2,7,15,19', -'24,,,41,47,55,60,,,10,20,27,,,39,46,,62,,5,11,,,30,35,,50,54,63,1,6', -'14,90,,,100,42,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,25,,33,,48,,59,,,89', -'93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,84,87,91,94,97,102,105,108,111,,,83,86,90,,151,100,,231,,,,,,,,', -',,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117', -'85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111', -',,83,86,16,21,90,,151,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,', -',,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112', -'114,116,84,87,91,94,97,102,105,108,111,,,83,86,16,21,90,,151,100,,,', -',,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113', -'115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105', -'108,111,,,83,86,16,21,90,,151,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,', -',,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106', -'109,112,114,116,84,87,91,94,97,102,105,108,111,,,83,86,16,21,90,,151', -'100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107', -'110,113,115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97', -'102,105,108,111,,,83,86,16,21,90,,,100,,,,,,,,,,,,,,,,,,,,,,101,,,,', -',82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103', -'106,109,112,114,116,84,87,91,94,97,102,105,108,111,,90,83,86,100,,,', -',,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113', -'115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105', -'108,111,,90,83,86,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89', -'93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,84,87,91,94,97,102,105,108,111,,90,83,86,100,,,,,,,,,,,,,,,,,,,', -',,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92', -'95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111,273,90', -'83,86,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104', -'107,110,113,115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91', -'94,97,102,105,108,111,,90,83,86,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82', -',,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106', -'109,112,114,116,84,87,91,94,97,102,105,108,111,,90,83,86,100,,,,,,,', -',,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115', -'117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108', -'111,,90,83,86,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93', -'96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114,116', -'84,87,91,94,97,102,105,108,111,,90,83,86,100,,,,,,,,,,,,,,,,,,,,,,101', -',,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98', -'103,106,109,112,114,116,84,87,91,94,97,102,105,108,111,,90,83,86,100', -',,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110', -'113,115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102', -'105,108,111,,90,83,86,100,,,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,', -',,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112', -'114,116,84,87,91,94,97,102,105,108,111,90,,,100,,,,,,,,,,,,,,,,,,,,', -',101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92', -'95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111,90,,,100', -',,,,,,,,,,,,,,,,,,,,,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110', -'113,115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102', -'105,108,111,101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117', -'85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111', -'101,,,,,,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92', -'95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111,101,,,', -',,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103', -'106,109,112,114,116,84,87,91,94,97,102,105,108,111,82,,,,,,,,,,,,89', -'93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,84,87,91,94,97,102,105,108,111,82,,,,,,,,,,,,89,93,96,99,104,107', -'110,113,115,117,85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97', -'102,105,108,111,82,,,,,,,,,,,,89,93,96,99,104,107,110,113,115,117,85', -'88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111,89', -'93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,84,87,91,94,97,102,105,108,111,89,93,96,99,104,107,110,113,115,117', -'85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111', -'89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,84,87,91,94,97,102,105,108,111,89,93,96,99,104,107,110,113,115,117', -'85,88,92,95,98,103,106,109,112,114,116,84,87,91,94,97,102,105,108,111', -'89,93,96,99,104,107,110,113,115,117,85,88,92,95,98,103,106,109,112,114', -'116,84,87,91,94,97,102,105,108,111' ] - racc_action_table = arr = Array.new(8210, nil) +'99,232,107,20,23,26,31,34,39,47,52,56,60,159,130,68,71,129,16,92,16', +'158,233,24,27,110,119,122,125,128,95,98,103,100,252,40,44,40,44,13,234', +'10,92,132,40,44,229,10,230,119,122,125,128,95,98,103,106,109,112,115', +'118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101', +'104,132,132,113,116,35,141,132,16,74,132,63,7,67,239,20,23,26,31,34', +'39,47,52,56,60,135,132,68,71,1,4,8,7,241,19,24,27,30,256,131,83,48,53', +'134,64,242,69,72,159,266,10,13,251,180,248,249,158,37,42,46,50,55,59', +'61,132,248,249,3,224,136,172,174,16,68,71,131,131,223,16,134,134,131', +'10,92,131,134,40,44,134,170,119,122,40,44,235,35,40,44,167,57,131,63', +'7,67,134,20,23,26,31,34,39,47,52,56,60,232,16,68,71,1,4,8,218,16,19', +'24,27,30,40,44,232,48,53,16,64,16,69,72,131,274,10,13,134,79,168,83', +'159,37,42,46,50,55,59,61,158,92,159,3,40,44,229,223,-167,-167,158,287', +'267,141,,252,92,,,40,44,229,10,-167,-167,276,10,246,162,,,35,,,,57,10', +'63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,159,,19,24,27,30', +',,158,48,53,,64,92,69,72,,,10,13,119,122,125,128,95,37,42,46,50,55,59', +'61,92,,10,3,162,,,119,122,125,128,95,98,103,106,109,112,115,118,121', +'124,127,94,97,102,105,108,111,40,44,235,35,,,236,57,,63,7,67,,20,23', +'26,31,34,39,47,52,56,60,92,,68,71,1,4,8,119,122,19,24,27,30,,,,48,53', +',64,92,69,72,,,10,13,119,122,125,128,95,37,42,46,50,55,59,61,92,,,3', +',,,119,122,125,128,95,98,103,106,109,112,115,118,121,124,127,94,97,102', +'105,108,111,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,92,', +'68,71,1,4,8,-167,-167,19,24,27,30,,,,48,53,,64,92,69,72,92,,10,13,-167', +'-167,,119,122,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,124,127,94,97,102,105,108,111,,,,35,,,,57,,63', +'7,67,,20,23,26,31,34,39,47,52,56,60,92,,68,71,1,4,8,-167,-167,19,24', +'27,30,,,,48,53,,64,92,69,72,92,,10,13,-167,-167,,-167,-167,37,42,46', +'50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106,109,112,115,118', +'121,124,127,94,97,102,105,108,111,,,,35,,,,57,,63,7,67,,20,23,26,31', +'34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,', +'10,13,,,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,124,127,94,97,102,105,108,111,,,,35,,,,57,,63', +'7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48', +'53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125', +'128,95,98,103,106,109,112,115,118,121,124,127,94,97,102,105,108,111', +',,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,', +'19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,89,,,,37,42,46,50,55,59,61', +'92,,,3,,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124,127', +'94,97,102,105,108,111,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106,109,112,115', +'118,121,,,,,,,,277,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56', +'60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42', +'46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106,109,112,115,118', +'121,124,127,94,97,102,105,108,111,,,,35,,,,57,,63,7,67,,20,23,26,31', +'34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,', +'10,13,,,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34', +'39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10', +'13,,,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106', +'109,112,115,118,121,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39', +'47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13', +',,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106,109', +'112,115,118,121,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106,109,112,92', +',,,,,,119,122,125,128,95,98,103,35,,,,57,,63,7,67,,20,23,26,31,34,39', +'47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13', +',,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103,106,109', +'112,92,,,,,,,119,122,125,128,95,98,103,35,,,,57,,63,7,67,,20,23,26,31', +'34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,', +'10,13,,,,,,37,42,46,50,55,59,61,92,,,3,,,,119,122,125,128,95,98,103', +'106,109,112,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67', +',20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53', +',64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,', +',,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1', +'4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59', +'61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34', +'39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10', +'13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57', +',63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30', +',,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,', +',,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,', +',68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46', +'50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23', +'26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69', +'72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,', +',35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19', +'24,27,30,,,,48,53,,64,,69,72,,,10,13,152,,,,,37,42,46,50,55,59,61,,', +',3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47', +'52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,', +',,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63', +'7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48', +'53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,', +',,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71', +'1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,258,,,,,37,42,46,50', +'55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,40,44,,57,,63,7,67,,20,23', +'26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69', +'72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,', +',35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19', +'24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3', +',,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67', +',20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53', +',64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,', +',,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1', +'4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59', +'61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34', +'39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10', +'13,152,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,', +',,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27', +'30,,,,48,53,,64,,69,72,,,10,13,152,,,,,37,42,46,50,55,59,61,,,,3,,,', +',,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56', +'60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,16,,,,,37', +'42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,40,44,,57,,63,7', +'67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48', +'53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,', +',,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71', +'1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55', +'59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31', +'34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,', +'10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,', +',,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27', +'30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,', +',,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60', +',,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,152,,,,,37,42', +'46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20', +'23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64', +',69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,', +',,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8', +',,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61', +',,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39', +'47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13', +',,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,', +'63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,', +',,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,', +',,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,', +'68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46', +'50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23', +'26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69', +'72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,', +',35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19', +'24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3', +',,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67', +',20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53', +',64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,', +',,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1', +'4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59', +'61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34', +'39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10', +'13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57', +',63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30', +',,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,', +',,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,', +',68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46', +'50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23', +'26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69', +'72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,', +',35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19', +'24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3', +',,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67', +',20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53', +',64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,', +',,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1', +'4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59', +'61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34', +'39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10', +'13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57', +',63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30', +',,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,', +',,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,', +',68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46', +'50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23', +'26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69', +'72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,', +',35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19', +'24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3', +',,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52', +'56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37', +'42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67', +',20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53', +',64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,', +',,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1', +'4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59', +'61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34', +'39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10', +'13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,57', +',63,7,67,,20,23,26,31,34,39,47,52,56,60,,,68,71,1,4,8,,,19,24,27,30', +',,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46,50,55,59,61,,,,3,,,,,,,,,', +',,,,,,,,,,,,,,,,,,35,,,,57,,63,7,67,,20,23,26,31,34,39,47,52,56,60,', +',68,71,1,4,8,,,19,24,27,30,,,,48,53,,64,,69,72,,,10,13,,,,,,37,42,46', +'50,55,59,61,99,,107,3,,,,20,23,26,31,34,39,47,52,56,60,,,,,,,,,110,', +'24,27,,,35,,100,,57,,63,,67,,,92,13,,,,,,119,122,125,128,95,98,103,106', +'109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126', +'93,96,101,104,228,,113,116,99,,107,,,245,,,74,,63,,67,,,,,,,,,,,,,110', +',,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115', +'118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101', +'104,,,113,116,,,,,,285,20,23,26,31,34,39,47,52,56,60,,,,,,,,,,,24,27', +',,,,,,,,,,,,,,13,,,,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,', +',,,,,92,,74,,63,,67,119,122,125,128,95,98,103,106,109,112,115,118,121', +'124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104,,,113', +'116,99,,107,,,288,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,,,,', +',119,122,125,128,95,98,103,106,109,112,115,118,121,124,127,94,97,102', +'105,108,111,114,117,120,123,126,93,96,101,104,228,,113,116,99,,107,', +',,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128', +'95,98,103,106,109,112,115,118,121,124,127,94,97,102,105,108,111,114', +'117,120,123,126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,', +',,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109', +'112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93', +'96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,', +',,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124', +'127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104,,,113,116', +'99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122', +'125,128,95,98,103,106,109,112,115,118,121,124,127,94,97,102,105,108', +'111,114,117,120,123,126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,', +',,,,,,,,,,110,,,,,,,,100,,,,,,,16,,92,,,,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123', +'126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,', +',100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118', +'121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104', +',,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,', +',,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124,127,94,97', +'102,105,108,111,114,117,120,123,126,93,96,101,104,,,113,116,99,,107', +',,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,226,,92,,,,,,,119,122,125', +'128,95,98,103,106,109,112,115,118,121,124,127,94,97,102,105,108,111', +'114,117,120,123,126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,', +',,,,,,110,,,,,,,,100,,,,,,,16,,92,,,,,,,119,122,125,128,95,98,103,106', +'109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126', +'93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100', +',,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124', +'127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104,,,113,116', +'99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122', +'125,128,95,98,103,106,109,112,115,118,121,124,127,94,97,102,105,108', +'111,114,117,120,123,126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,', +',,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123', +'126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,', +',100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118', +'121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104', +',,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,', +',,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124,127,94,97', +'102,105,108,111,114,117,120,123,126,93,96,101,104,,,113,116,99,,107', +',,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128', +'95,98,103,106,109,112,115,118,121,124,127,94,97,102,105,108,111,114', +'117,120,123,126,93,96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,', +',,110,,,,,,,,100,,,,,,,16,,92,,,,,,,119,122,125,128,95,98,103,106,109', +'112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93', +'96,101,104,,,113,116,99,,107,,,,,,,,,,,,,,,,,,,,,,,110,,,,,,,,100,,', +',,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124', +'127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104,110,,113', +'116,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115', +'118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101', +'104,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109', +'112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93', +'96,101,104,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123', +'126,93,96,101,104,110,,,,,,,,100,,,,,,,,,92,,,,,,,119,122,125,128,95', +'98,103,106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117', +'120,123,126,93,96,101,104,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98', +'103,106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120', +'123,126,93,96,101,104,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103', +'106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123', +'126,93,96,101,104,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106', +'109,112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126', +'93,96,101,104,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109', +'112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93', +'96,101,104,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112', +'115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96', +'101,104,100,,,,,,,,,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115', +'118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101', +'104,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118,121,124,127', +'94,97,102,105,108,111,114,117,120,123,126,93,96,101,104,92,,,,,,,119', +'122,125,128,95,98,103,106,109,112,115,118,121,124,127,94,97,102,105', +'108,111,114,117,120,123,126,93,96,101,104,92,,,,,,,119,122,125,128,95', +'98,103,106,109,112,115,118,121,124,127,94,97,102,105,108,111,114,117', +'120,123,126,93,96,101,104,92,,,,,,,119,122,125,128,95,98,103,106,109', +'112,115,118,121,124,127,94,97,102,105,108,111,114,117,120,123,126,93', +'96,101,104,92,,,,,,,119,122,125,128,95,98,103,106,109,112,115,118,121', +'124,127,94,97,102,105,108,111,114,117,120,123,126,93,96,101,104' ] + racc_action_table = arr = Array.new(8814, nil) idx = 0 clist.each do |str| str.split(',', -1).each do |i| @@ -295,291 +319,312 @@ def on_error(error_token_id, error_value, value_stack) end clist = [ -'0,245,101,242,0,0,0,0,0,0,0,0,0,0,212,80,0,0,0,0,143,143,0,0,0,69,69', -'0,0,143,0,214,0,0,29,29,0,0,200,0,0,0,0,0,0,224,200,141,141,0,78,47', -'47,47,47,47,47,47,47,47,47,128,128,130,128,131,212,136,128,200,47,47', -'74,224,245,242,204,0,0,0,155,0,1,0,47,0,1,1,1,1,1,1,1,1,1,1,175,144', -'1,1,1,1,176,214,1,1,1,214,214,1,1,196,1,198,1,1,18,224,1,1,217,1,1,1', -'1,1,1,11,47,211,47,1,47,135,135,135,135,135,135,135,135,135,135,204', -',256,,204,48,256,256,,135,135,144,144,48,,205,262,,1,,1,5,1,135,1,5', -'5,5,5,5,5,5,5,5,5,,48,5,5,5,5,,254,5,5,5,254,254,5,5,,5,,5,5,271,271', -'5,5,,5,5,5,5,5,5,,135,,135,5,135,222,222,222,222,222,222,222,222,222', -'222,205,262,262,263,205,262,,263,263,222,222,199,179,179,,125,61,246', -'5,199,5,6,5,222,5,6,6,6,6,6,6,6,6,6,6,67,67,6,6,6,6,,199,6,6,6,26,26', -'6,6,,6,,6,6,173,173,6,6,222,6,6,6,6,6,6,,222,,222,6,222,247,247,247', -'247,247,247,247,247,247,247,125,61,246,246,125,61,246,223,,247,247,223', -'223,126,,120,53,,6,,6,9,6,247,6,9,9,9,9,9,9,9,9,9,9,120,53,9,9,9,9,', -'274,9,9,9,274,274,9,9,,9,,9,9,170,170,9,9,,9,9,9,9,9,9,,247,,247,9,247', -'73,73,120,120,53,148,148,,126,,120,53,126,,120,53,152,152,,152,213,213', -',213,,152,76,76,9,213,9,10,9,,9,10,10,10,10,10,10,10,10,10,10,132,132', -'10,10,10,10,77,77,10,10,10,253,253,10,10,,10,,10,10,122,122,10,10,,10', -'10,10,10,10,10,,,,,10,191,191,191,191,191,191,191,191,191,191,191,191', -'191,191,191,191,191,191,191,191,191,208,208,,208,,,,,10,208,10,272,10', -',10,272,272,272,272,272,272,272,272,272,272,,,272,272,272,272,,,272', -'272,272,,,272,272,,272,,272,272,,,272,272,,272,272,272,272,272,272,', -',,,272,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160', -'160,160,160,160,160,118,118,,118,,118,272,272,272,,272,14,272,,272,14', -'14,14,14,14,14,14,14,14,14,,,14,14,14,14,,,14,14,14,,,14,14,,14,,14', -'14,,,14,14,,14,14,14,14,14,14,,,,,14,189,189,189,189,189,189,189,189', -'189,189,189,189,189,189,189,189,189,189,189,189,189,190,190,190,190', -'190,190,190,,14,,14,226,14,,14,226,226,226,226,226,226,226,226,226,226', -',,226,226,226,226,,,226,226,226,,,226,226,,226,,226,226,,,226,226,,226', -'226,226,226,226,226,,,,,226,184,184,184,184,184,184,184,184,184,184', -'184,184,184,184,184,184,184,184,184,184,184,188,188,188,188,188,188', -'188,,226,,226,23,226,,226,23,23,23,23,23,23,23,23,23,23,,,23,23,23,23', -',,23,23,23,,,23,23,,23,,23,23,,,23,23,,23,23,23,23,23,23,,,,,23,168', -'168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168', -'168,168,168,185,185,185,185,185,,23,23,23,,23,25,23,,23,25,25,25,25', -'25,25,25,25,25,25,,,25,25,25,25,,,25,25,25,,,25,25,,25,,25,25,,,25,25', -',25,25,25,25,25,25,,,,,25,166,166,166,166,166,166,166,166,166,166,166', -'166,166,166,166,166,166,166,166,166,166,182,182,182,182,182,,25,25,25', -',25,233,25,,25,233,233,233,233,233,233,233,233,233,233,,,233,233,233', -'233,,,233,233,233,,,233,233,,233,,233,233,,,233,233,,233,233,233,233', -'233,233,,,,,233,187,187,187,187,187,187,187,187,187,187,187,187,187', -'187,187,187,187,187,187,187,187,,,,,,,233,233,233,,233,264,233,,233', -'264,264,264,264,264,264,264,264,264,264,,,264,264,264,264,,,264,264', -'264,,,264,264,,264,,264,264,,,264,264,,264,264,264,264,264,264,,,,,264', -'163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163', -'163,163,163,163,,,,,,,264,264,264,,264,193,264,,264,193,193,193,193', -'193,193,193,193,193,193,,,193,193,193,193,,,193,193,193,,,193,193,,193', -',193,193,,,193,193,,193,193,193,193,193,193,,,,,193,178,178,178,178', -'178,178,178,178,178,178,178,178,178,172,172,172,172,172,172,172,172', -'172,172,172,172,172,,,,193,,193,33,193,,193,33,33,33,33,33,33,33,33', -'33,33,,,33,33,33,33,,,33,33,33,,,33,33,,33,,33,33,,,33,33,,33,33,33', -'33,33,33,,,,,33,181,181,181,181,181,181,181,181,181,181,181,181,181', -'169,169,169,169,169,169,169,169,169,169,169,169,169,,,,33,,33,39,33', -',33,39,39,39,39,39,39,39,39,39,39,,,39,39,39,39,,,39,39,39,,,39,39,', -'39,,39,39,,,39,39,,39,39,39,39,39,39,,,,,39,164,164,164,164,164,164', -'164,164,164,164,161,161,161,161,161,161,161,161,161,161,192,192,192', -'192,192,192,192,,,39,,39,42,39,,39,42,42,42,42,42,42,42,42,42,42,,,42', -'42,42,42,,,42,42,42,,,42,42,,42,,42,42,,,42,42,,42,42,42,42,42,42,,', -',,42,167,167,167,167,167,167,167,167,167,167,,,,,,,,,,,,,,,,,,,,42,', -'42,46,42,,42,46,46,46,46,46,46,46,46,46,46,,,46,46,46,46,,,46,46,46', -',,46,46,,46,,46,46,,,46,46,,46,46,46,46,46,46,,,,,46,,,,,,,,,,,,,,,', -',,,,,,,,,,,,,,46,,46,149,46,,46,149,149,149,149,149,149,149,149,149', -'149,,,149,149,149,149,,,149,149,149,,,149,149,,149,,149,149,,,149,149', -',149,149,149,149,149,149,,,,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,149,149', -'149,,149,234,149,,149,234,234,234,234,234,234,234,234,234,234,,,234', -'234,234,234,,,234,234,234,,,234,234,,234,,234,234,,,234,234,,234,234', -'234,234,234,234,,,,,234,,,,,,,,,,,,,,,,,,,,,,,,,,,,234,234,234,,234', -'50,234,,234,50,50,50,50,50,50,50,50,50,50,,,50,50,50,50,,,50,50,50,', -',50,50,,50,,50,50,,,50,50,,50,50,50,50,50,50,,,,,50,,,,,,,,,,,,,,,,', -',,,,,,,,,,,,,50,,50,194,50,,50,194,194,194,194,194,194,194,194,194,194', -',,194,194,194,194,,,194,194,194,,,194,194,,194,,194,194,,,194,194,,194', -'194,194,194,194,194,,,,,194,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,194,,194,54', -'194,,194,54,54,54,54,54,54,54,54,54,54,,,54,54,54,54,,,54,54,54,,,54', -'54,,54,,54,54,,,54,54,,54,54,54,54,54,54,,,,,54,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,,54,,54,55,54,,54,55,55,55,55,55,55,55,55,55,55,,,55,55,55,55', -',,55,55,55,,,55,55,,55,,55,55,,,55,55,,55,55,55,55,55,55,,,,,55,,,,', -',,,,,,,,,,,,,,,,,,,,,,,,,55,,55,59,55,,55,59,59,59,59,59,59,59,59,59', -'59,,,59,59,59,59,,,59,59,59,,,59,59,,59,,59,59,,,59,59,,59,59,59,59', -'59,59,,,,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,59,59,,59,60,59,,59,60,60', -'60,60,60,60,60,60,60,60,,,60,60,60,60,,,60,60,60,,,60,60,,60,,60,60', -',,60,60,,60,60,60,60,60,60,,,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,60,60,60', -',60,146,60,,60,146,146,146,146,146,146,146,146,146,146,,,146,146,146', -'146,,,146,146,146,,,146,146,,146,,146,146,,,146,146,,146,146,146,146', -'146,146,,,,,146,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,146,,146,62,146,,146,62', -'62,62,62,62,62,62,62,62,62,,,62,62,62,62,,,62,62,62,,,62,62,,62,,62', -'62,,,62,62,,62,62,62,62,62,62,,,,,62,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,62', -',62,117,62,,62,117,117,117,117,117,117,117,117,117,117,,,117,117,117', -'117,,,117,117,117,,,117,117,,117,,117,117,,,117,117,,117,117,117,117', -'117,117,,,,,117,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,117,,117,197,117,,117,197', -'197,197,197,197,197,197,197,197,197,,,197,197,197,197,,,197,197,197', -',,197,197,,197,,197,197,,,197,197,,197,197,197,197,197,197,,,,,197,', -',,,,,,,,,,,,,,,,,,,,,,,,,,197,197,197,,197,140,197,,197,140,140,140', -'140,140,140,140,140,140,140,,,140,140,140,140,,,140,140,140,,,140,140', -',140,,140,140,,,140,140,,140,140,140,140,140,140,,,,,140,,,,,,,,,,,', -',,,,,,,,,,,,,,,,,,140,,140,139,140,,140,139,139,139,139,139,139,139', -'139,139,139,,,139,139,139,139,,,139,139,139,,,139,139,,139,,139,139', -',,139,139,,139,139,139,139,139,139,,,,,139,,,,,,,,,,,,,,,,,,,,,,,,,', -',,,,139,,139,137,139,,139,137,137,137,137,137,137,137,137,137,137,,', -'137,137,137,137,,,137,137,137,,,137,137,,137,,137,137,,,137,137,,137', -'137,137,137,137,137,,,,,137,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,137,,137,239', -'137,,137,239,239,239,239,239,239,239,239,239,239,,,239,239,239,239,', -',239,239,239,,,239,239,,239,,239,239,,,239,239,,239,239,239,239,239', -'239,,,,,239,,,,,,,,,,,,,,,,,,,,,,,,,,,,239,239,239,,239,72,239,,239', -'72,72,72,72,72,72,72,72,72,72,,,72,72,72,72,,,72,72,72,,,72,72,,72,', -'72,72,,,72,72,,72,72,72,72,72,72,,,,,72,,,,,,,,,,,,,,,,,,,,,,,,,,,,', -',72,,72,259,72,,72,259,259,259,259,259,259,259,259,259,259,,,259,259', -'259,259,,,259,259,259,,,259,259,,259,,259,259,,,259,259,,259,259,259', -'259,259,259,,,,,259,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,259,,259,218,259,,259', -'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,75,218,,218,75,75,75,75,75,75', -'75,75,75,75,,,75,75,75,75,,,75,75,75,,,75,75,,75,,75,75,,,75,75,,75', -'75,75,75,75,75,,,,,75,,,,,,,,,,,,,,,,,,,,,,,,,,,,75,75,75,,75,255,75', -',75,255,255,255,255,255,255,255,255,255,255,,,255,255,255,255,,,255', -'255,255,,,255,255,,255,,255,255,,,255,255,,255,255,255,255,255,255,', -',,,255,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255,,255,203,255,,255,203,203,203', -'203,203,203,203,203,203,203,,,203,203,203,203,,,203,203,203,,,203,203', -',203,,203,203,,,203,203,,203,203,203,203,203,203,,,,,203,,,,,,,,,,,', -',,,,,,,,,,,,,,,,,,203,,203,124,203,,203,124,124,124,124,124,124,124', -'124,124,124,,,124,124,124,124,,,124,124,124,,,124,124,,124,,124,124', -',,124,124,,124,124,124,124,124,124,,,,,124,,,,,,,,,,,,,,,,,,,,,,,,,', -',,,,124,,124,79,124,,124,79,79,79,79,79,79,79,79,79,79,,,79,79,79,79', -',,79,79,79,,,79,79,,79,,79,79,,,79,79,,79,79,79,79,79,79,,,,,79,,,,', -',,,,,,,,,,,,,,,,,,,,,,,79,79,79,,79,249,79,,79,249,249,249,249,249,249', -'249,249,249,249,,,249,249,249,249,,,249,249,249,,,249,249,,249,,249', -'249,,,249,249,,249,249,249,249,249,249,,,,,249,,,,,,,,,,,,,,,,,,,,,', -',,,,,,249,249,249,,249,81,249,,249,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,82,81,,81,82,82,82,82,82,82', -'82,82,82,82,,,82,82,82,82,,,82,82,82,,,82,82,,82,,82,82,,,82,82,,82', -'82,82,82,82,82,,,,,82,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,82,,82,83,82,,82', -'83,83,83,83,83,83,83,83,83,83,,,83,83,83,83,,,83,83,83,,,83,83,,83,', -'83,83,,,83,83,,83,83,83,83,83,83,,,,,83,,,,,,,,,,,,,,,,,,,,,,,,,,,,', -',83,,83,84,83,,83,84,84,84,84,84,84,84,84,84,84,,,84,84,84,84,,,84,84', -'84,,,84,84,,84,,84,84,,,84,84,,84,84,84,84,84,84,,,,,84,,,,,,,,,,,,', -',,,,,,,,,,,,,,,,,84,,84,85,84,,84,85,85,85,85,85,85,85,85,85,85,,,85', -'85,85,85,,,85,85,85,,,85,85,,85,,85,85,,,85,85,,85,85,85,85,85,85,,', -',,85,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,85,,85,86,85,,85,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,,86,87,86,,86', -'87,87,87,87,87,87,87,87,87,87,,,87,87,87,87,,,87,87,87,,,87,87,,87,', -'87,87,,,87,87,,87,87,87,87,87,87,,,,,87,,,,,,,,,,,,,,,,,,,,,,,,,,,,', -',87,,87,88,87,,87,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,90,88,,88,90,90,90,90,90,90,90,90,90,90,,,90', -'90,90,90,,,90,90,90,,,90,90,,90,,90,90,,,90,90,,90,90,90,90,90,90,,', -',,90,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,90,,90,91,90,,90,91,91,91,91,91,91', -'91,91,91,91,,,91,91,91,91,,,91,91,91,,,91,91,,91,,91,91,,,91,91,,91', -'91,91,91,91,91,,,,,91,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,91,,91,92,91,,91', -'92,92,92,92,92,92,92,92,92,92,,,92,92,92,92,,,92,92,92,,,92,92,,92,', -'92,92,,,92,92,,92,92,92,92,92,92,,,,,92,,,,,,,,,,,,,,,,,,,,,,,,,,,,', -',92,,92,94,92,,92,94,94,94,94,94,94,94,94,94,94,,,94,94,94,94,,,94,94', -'94,,,94,94,,94,,94,94,,,94,94,,94,94,94,94,94,94,,,,,94,,,,,,,,,,,,', -',,,,,,,,,,,,,,,,,94,,94,95,94,,94,95,95,95,95,95,95,95,95,95,95,,,95', -'95,95,95,,,95,95,95,,,95,95,,95,,95,95,,,95,95,,95,95,95,95,95,95,,', -',,95,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,95,,95,96,95,,95,96,96,96,96,96,96', -'96,96,96,96,,,96,96,96,96,,,96,96,96,,,96,96,,96,,96,96,,,96,96,,96', -'96,96,96,96,96,,,,,96,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96,,96,97,96,,96', -'97,97,97,97,97,97,97,97,97,97,,,97,97,97,97,,,97,97,97,,,97,97,,97,', -'97,97,,,97,97,,97,97,97,97,97,97,,,,,97,,,,,,,,,,,,,,,,,,,,,,,,,,,,', -',97,,97,98,97,,97,98,98,98,98,98,98,98,98,98,98,,,98,98,98,98,,,98,98', -'98,,,98,98,,98,,98,98,,,98,98,,98,98,98,98,98,98,,,,,98,,,,,,,,,,,,', -',,,,,,,,,,,,,,,,,98,,98,99,98,,98,99,99,99,99,99,99,99,99,99,99,,,99', -'99,99,99,,,99,99,99,,,99,99,,99,,99,99,,,99,99,,99,99,99,99,99,99,,', -',,99,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,99,,99,100,99,,99,100,100,100,100', -'100,100,100,100,100,100,,,100,100,100,100,,,100,100,100,,,100,100,,100', -',100,100,,,100,100,,100,100,100,100,100,100,,,,,100,,,,,,,,,,,,,,,,', -',,,,,,,,,,,,,100,,100,202,100,,100,202,202,202,202,202,202,202,202,202', -'202,,,202,202,202,202,,,202,202,202,,,202,202,,202,,202,202,,,202,202', -',202,202,202,202,202,202,,,,,202,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,202,,202', -'102,202,,202,102,102,102,102,102,102,102,102,102,102,,,102,102,102,102', -',,102,102,102,,,102,102,,102,,102,102,,,102,102,,102,102,102,102,102', -'102,,,,,102,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,102,,102,103,102,,102,103,103', -'103,103,103,103,103,103,103,103,,,103,103,103,103,,,103,103,103,,,103', -'103,,103,,103,103,,,103,103,,103,103,103,103,103,103,,,,,103,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,,103,,103,104,103,,103,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,,104,105,104,,104,105,105,105,105,105,105,105,105,105,105', -',,105,105,105,105,,,105,105,105,,,105,105,,105,,105,105,,,105,105,,105', -'105,105,105,105,105,,,,,105,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,105,,105,106', -'105,,105,106,106,106,106,106,106,106,106,106,106,,,106,106,106,106,', -',106,106,106,,,106,106,,106,,106,106,,,106,106,,106,106,106,106,106', -'106,,,,,106,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,106,,106,107,106,,106,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,108,107,,107,108,108,108,108,108,108', -'108,108,108,108,,,108,108,108,108,,,108,108,108,,,108,108,,108,,108', -'108,,,108,108,,108,108,108,108,108,108,,,,,108,,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,108,,108,109,108,,108,109,109,109,109,109,109,109,109,109,109', -',,109,109,109,109,,,109,109,109,,,109,109,,109,,109,109,,,109,109,,109', -'109,109,109,109,109,,,,,109,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,109,,109,110', -'109,,109,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,111,110,,110,111,111', -'111,111,111,111,111,111,111,111,,,111,111,111,111,,,111,111,111,,,111', -'111,,111,,111,111,,,111,111,,111,111,111,111,111,111,,,,,111,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,,111,,111,112,111,,111,112,112,112,112,112,112', -'112,112,112,112,,,112,112,112,112,,,112,112,112,,,112,112,,112,,112', -'112,,,112,112,,112,112,112,112,112,112,,,,,112,,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,112,,112,113,112,,112,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,114', -'113,,113,114,114,114,114,114,114,114,114,114,114,,,114,114,114,114,', -',114,114,114,,,114,114,,114,,114,114,,,114,114,,114,114,114,114,114', -'114,,,,,114,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,114,,114,115,114,,114,115,115', -'115,115,115,115,115,115,115,115,,,115,115,115,115,,,115,115,115,,,115', -'115,,115,,115,115,,,115,115,,115,115,115,115,115,115,,,,,115,,,,,,,', -',,,,,,,,,,,,,,,,,,,,,,115,,115,116,115,,115,116,116,116,116,116,116', -'116,116,116,116,,,116,116,116,116,,,116,116,116,,,116,116,,116,,116', -'116,,,116,116,,116,116,116,116,116,116,,,,,116,,,,,,,,,,,,,,,,,,,,,', -',,,,,,,,116,,116,63,116,,116,63,63,63,63,63,63,63,63,63,63,,,63,63,63', -'63,,,63,63,63,,,63,63,,63,,63,63,,,63,63,,63,63,63,63,63,63,207,,,207', -'63,,,,,,,,,,,,,,,,,,,,,207,,,,,,207,,,63,,63,,63,,63,,,207,207,207,207', +'165,154,165,135,135,135,135,135,135,135,135,135,135,237,22,246,246,22', +'242,194,241,237,158,135,135,165,194,194,194,194,194,194,194,165,226', +'282,282,18,18,135,159,226,165,220,154,154,154,237,154,165,165,165,165', +'165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165', +'165,165,165,165,165,165,165,165,165,76,25,165,165,246,30,51,35,135,157', +'135,98,135,165,98,98,98,98,98,98,98,98,98,98,25,156,98,98,98,98,98,83', +'172,98,98,98,98,228,220,15,98,98,220,98,173,98,98,235,238,98,98,224', +'88,244,244,235,98,98,98,98,98,98,98,75,222,222,98,141,25,81,81,83,129', +'129,76,25,140,222,76,25,51,235,183,157,51,12,12,157,79,183,183,238,238', +'238,98,88,88,71,98,156,98,3,98,156,3,3,3,3,3,3,3,3,3,3,240,174,3,3,3', +'3,3,132,130,3,3,3,3,235,235,219,3,3,274,3,8,3,3,75,253,3,3,75,5,72,85', +'63,3,3,3,3,3,3,3,63,77,263,3,240,240,240,198,77,77,263,283,240,110,', +'253,155,,,219,219,219,253,155,155,253,63,219,63,,,3,,,,3,263,3,4,3,', +'4,4,4,4,4,4,4,4,4,4,,,4,4,4,4,4,162,,4,4,4,4,,,162,4,4,,4,186,4,4,,', +'4,4,186,186,186,186,186,4,4,4,4,4,4,4,199,,162,4,162,,,199,199,199,199', +'199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199', +'160,160,160,4,,,160,4,,4,121,4,,121,121,121,121,121,121,121,121,121', +'121,214,,121,121,121,121,121,214,214,121,121,121,121,,,,121,121,,121', +'191,121,121,,,121,121,191,191,191,191,191,121,121,121,121,121,121,121', +'196,,,121,,,,196,196,196,196,196,196,196,196,196,196,196,196,196,196', +'196,196,196,196,196,196,196,,,,121,,,,121,,121,7,121,,7,7,7,7,7,7,7', +'7,7,7,151,,7,7,7,7,7,151,151,7,7,7,7,,,,7,7,,7,143,7,7,211,,7,7,143', +'143,,211,211,7,7,7,7,7,7,7,205,,,7,,,,205,205,205,205,205,205,205,205', +'205,205,205,205,205,205,205,205,205,205,205,205,205,,,,7,,,,7,,7,277', +'7,,277,277,277,277,277,277,277,277,277,277,147,,277,277,277,277,277', +'147,147,277,277,277,277,,,,277,277,,277,145,277,277,144,,277,277,145', +'145,,144,144,277,277,277,277,277,277,277,207,,,277,,,,207,207,207,207', '207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207', -'207,207,207,207,207,207,207,207,207,,,207,207,123,,123,123,,207,,,,', -',,,,,,,,,,,,,,,123,,,,,,123,,,,,,,,,,,,123,123,123,123,123,123,123,123', -'123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123', -'123,123,123,123,123,,,123,123,123,123,252,,252,252,,,,,,,,,,,,,,,,,', -',,,,252,,,,,,252,,,,,,,,,,,,252,252,252,252,252,252,252,252,252,252', -'252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252', -'252,252,252,,,252,252,252,252,121,,121,121,,,,,,,,,,,,,,,,,,,,,,121', -',,,,,121,,,,,,,,,,,,121,121,121,121,121,121,121,121,121,121,121,121', -'121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121', -'121,,,121,121,121,121,70,,70,70,,,,,,,,,,,,,,,,,,,,,,70,,,,,,70,,,,', -',,,,,,,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70', -'70,70,70,70,70,70,70,70,70,,,70,70,70,70,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,229,,,229,,,,,,,,,,,,,,,,,,,,,,229,,,', -',,229,,,,,,,,,,,,229,229,229,229,229,229,229,229,229,229,229,229,229', -'229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229', -',32,229,229,32,,,,,,,,,,,,,,,,,,,,,,32,,,,,,32,,,,,,,,,,,,32,32,32,32', -'32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32', -'32,32,32,,221,32,32,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,,268,221,221,268', -',,,,,,,,,,,,,,,,,,,,,268,,,,,,268,,,,,,,,,,,,268,268,268,268,268,268', -'268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268', -'268,268,268,268,268,268,268,268,244,268,268,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,244,,157,244,244,157,,,,,,,,,,,,,,,,,,,,,,157,,,,,,157,,,,,,,,,', -',,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157', -'157,157,157,157,157,157,157,157,157,157,157,157,157,,119,157,157,119', -',,,,,,,,,,,,,,,,,,,,,119,,,,,,119,,,,,,,,,,,,119,119,119,119,119,119', -'119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119', -'119,119,119,119,119,119,119,,220,119,119,220,,,,,,,,,,,,,,,,,,,,,,220', -',,,,,220,,,,,,,,,,,,220,220,220,220,220,220,220,220,220,220,220,220', -'220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220', -'220,,142,220,220,142,,,,,,,,,,,,,,,,,,,,,,142,,,,,,142,,,,,,,,,,,,142', -'142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142', -'142,142,142,142,142,142,142,142,142,142,142,142,,230,142,142,230,,,', -',,,,,,,,,,,,,,,,,,230,,,,,,230,,,,,,,,,,,,230,230,230,230,230,230,230', -'230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230', -'230,230,230,230,230,230,,159,230,230,159,,,,,,,,,,,,,,,,,,,,,,159,,', -',,,159,,,,,,,,,,,,159,159,159,159,159,159,159,159,159,159,159,159,159', -'159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159', -'162,,,162,,,,,,,,,,,,,,,,,,,,,,162,,,,,,162,,,,,,,,,,,,162,162,162,162', -'162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162', -'162,162,162,162,162,162,162,162,162,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,209,209', -'209,71,,,,,,71,,,,,,,,,,,,71,71,71,71,71,71,71,71,71,71,71,71,71,71', -'71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,174,,,,,,174,,,,,,,', -',,,,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174', -'174,174,174,174,174,174,174,174,174,174,174,174,174,174,165,,,,,,165', -',,,,,,,,,,,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165', -'165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,147,,,,', -',,,,,,,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147', -'147,147,147,147,147,147,147,147,147,147,147,147,147,147,158,,,,,,,,', -',,,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158', -'158,158,158,158,158,158,158,158,158,158,158,158,158,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,177,177,177,177,177,177,177,177,177,177,177,177,177', -'177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177', -'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,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,171,171,171,171,171,171,171,171', -'171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171', -'171,171,171,171,171,183,183,183,183,183,183,183,183,183,183,183,183', -'183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183', -'183' ] - racc_action_check = arr = Array.new(8210, nil) +',,,277,,,,277,,277,258,277,,258,258,258,258,258,258,258,258,258,258', +',,258,258,258,258,258,,,258,258,258,258,,,,258,258,,258,,258,258,,,258', +'258,,,,,,258,258,258,258,258,258,258,193,,,258,,,,193,193,193,193,193', +'193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,,,,258', +',,,258,,258,257,258,,257,257,257,257,257,257,257,257,257,257,,,257,257', +'257,257,257,,,257,257,257,257,,,,257,257,,257,,257,257,,,257,257,,,', +',,257,257,257,257,257,257,257,209,,,257,,,,209,209,209,209,209,209,209', +'209,209,209,209,209,209,209,209,209,209,209,209,209,209,,,,257,,,,257', +',257,16,257,,16,16,16,16,16,16,16,16,16,16,,,16,16,16,16,16,,,16,16', +'16,16,,,,16,16,,16,,16,16,,,16,16,,16,,,,16,16,16,16,16,16,16,202,,', +'16,,,,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202', +'202,202,202,202,202,,,,16,,,,16,,16,256,16,,256,256,256,256,256,256', +'256,256,256,256,,,256,256,256,256,256,,,256,256,256,256,,,,256,256,', +'256,,256,256,,,256,256,,,,,,256,256,256,256,256,256,256,210,,,256,,', +',210,210,210,210,210,210,210,210,210,210,210,210,210,,,,,,,,256,,,,256', +',,,256,,256,19,256,,19,19,19,19,19,19,19,19,19,19,,,19,19,19,19,19,', +',19,19,19,19,,,,19,19,,19,,19,19,,,19,19,,,,,,19,19,19,19,19,19,19,190', +',,19,,,,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190', +'190,190,190,190,190,190,,,,19,,,,19,,19,252,19,,252,252,252,252,252', +'252,252,252,252,252,,,252,252,252,252,252,,,252,252,252,252,,,,252,252', +',252,,252,252,,,252,252,,,,,,252,252,252,252,252,252,252,185,,,252,', +',,185,185,185,185,185,185,185,185,185,185,185,185,185,,,,,,,,,,,,252', +',,,252,,252,249,252,,249,249,249,249,249,249,249,249,249,249,,,249,249', +'249,249,249,,,249,249,249,249,,,,249,249,,249,,249,249,,,249,249,,,', +',,249,249,249,249,249,249,249,182,,,249,,,,182,182,182,182,182,182,182', +'182,182,182,182,182,182,,,,,,,,,,,,249,,,,249,,249,248,249,,248,248', +'248,248,248,248,248,248,248,248,,,248,248,248,248,248,,,248,248,248', +'248,,,,248,248,,248,,248,248,,,248,248,,,,,,248,248,248,248,248,248', +'248,213,,,248,,,,213,213,213,213,213,213,213,213,213,213,213,213,213', +',,,,,,,,,,,248,,,,248,,248,234,248,,234,234,234,234,234,234,234,234', +'234,234,,,234,234,234,234,234,,,234,234,234,234,,,,234,234,,234,,234', +'234,,,234,234,,,,,,234,234,234,234,234,234,234,206,,,234,,,,206,206', +'206,206,206,206,206,206,206,206,200,,,,,,,200,200,200,200,200,200,200', +'234,,,,234,,234,233,234,,233,233,233,233,233,233,233,233,233,233,,,233', +'233,233,233,233,,,233,233,233,233,,,,233,233,,233,,233,233,,,233,233', +',,,,,233,233,233,233,233,233,233,208,,,233,,,,208,208,208,208,208,208', +'208,208,208,208,197,,,,,,,197,197,197,197,197,197,197,233,,,,233,,233', +'37,233,,37,37,37,37,37,37,37,37,37,37,,,37,37,37,37,37,,,37,37,37,37', +',,,37,37,,37,,37,37,,,37,37,,,,,,37,37,37,37,37,37,37,203,,,37,,,,203', +'203,203,203,203,203,203,203,203,203,,,,,,,,,,,,,,,37,,,,37,,37,42,37', +',42,42,42,42,42,42,42,42,42,42,,,42,42,42,42,42,,,42,42,42,42,,,,42', +'42,,42,,42,42,,,42,42,,,,,,42,42,42,42,42,42,42,,,,42,,,,,,,,,,,,,,', +',,,,,,,,,,,,,42,,,,42,,42,46,42,,46,46,46,46,46,46,46,46,46,46,,,46', +'46,46,46,46,,,46,46,46,46,,,,46,46,,46,,46,46,,,46,46,,,,,,46,46,46', +'46,46,46,46,,,,46,,,,,,,,,,,,,,,,,,,,,,,,,,,,46,,,,46,,46,48,46,,48', +'48,48,48,48,48,48,48,48,48,,,48,48,48,48,48,,,48,48,48,48,,,,48,48,', +'48,,48,48,,,48,48,,,,,,48,48,48,48,48,48,48,,,,48,,,,,,,,,,,,,,,,,,', +',,,,,,,,,48,,,,48,,48,50,48,,50,50,50,50,50,50,50,50,50,50,,,50,50,50', +'50,50,,,50,50,50,50,,,,50,50,,50,,50,50,,,50,50,,,,,,50,50,50,50,50', +'50,50,,,,50,,,,,,,,,,,,,,,,,,,,,,,,,,,,50,,,,50,,50,231,50,,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,53,231,,53,53', +'53,53,53,53,53,53,53,53,,,53,53,53,53,53,,,53,53,53,53,,,,53,53,,53', +',53,53,,,53,53,,,,,,53,53,53,53,53,53,53,,,,53,,,,,,,,,,,,,,,,,,,,,', +',,,,,,53,,,,53,,53,55,53,,55,55,55,55,55,55,55,55,55,55,,,55,55,55,55', +'55,,,55,55,55,55,,,,55,55,,55,,55,55,,,55,55,,,,,,55,55,55,55,55,55', +'55,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,,,55,,,,55,,55,57,55,,57,57,57,57', +'57,57,57,57,57,57,,,57,57,57,57,57,,,57,57,57,57,,,,57,57,,57,,57,57', +',,57,57,57,,,,,57,57,57,57,57,57,57,,,,57,,,,,,,,,,,,,,,,,,,,,,,,,,', +',57,,,,57,,57,59,57,,59,59,59,59,59,59,59,59,59,59,,,59,59,59,59,59', +',,59,59,59,59,,,,59,59,,59,,59,59,,,59,59,,,,,,59,59,59,59,59,59,59', +',,,59,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,59,,59,120,59,,120,120,120,120', +'120,120,120,120,120,120,,,120,120,120,120,120,,,120,120,120,120,,,,120', +'120,,120,,120,120,,,120,120,,,,,,120,120,120,120,120,120,120,,,,120', +',,,,,,,,,,,,,,,,,,,,,,,,,,,120,,,,120,,120,229,120,,229,229,229,229', +'229,229,229,229,229,229,,,229,229,229,229,229,,,229,229,229,229,,,,229', +'229,,229,,229,229,,,229,229,229,,,,,229,229,229,229,229,229,229,,,,229', +',,,,,,,,,,,,,,,,,,,,,,,,,,,229,229,229,,229,,229,64,229,,64,64,64,64', +'64,64,64,64,64,64,,,64,64,64,64,64,,,64,64,64,64,,,,64,64,,64,,64,64', +',,64,64,,,,,,64,64,64,64,64,64,64,,,,64,,,,,,,,,,,,,,,,,,,,,,,,,,,,64', +',,,64,,64,67,64,,67,67,67,67,67,67,67,67,67,67,,,67,67,67,67,67,,,67', +'67,67,67,,,,67,67,,67,,67,67,,,67,67,,,,,,67,67,67,67,67,67,67,,,,67', +',,,,,,,,,,,,,,,,,,,,,,,,,,,67,,,,67,,67,69,67,,69,69,69,69,69,69,69', +'69,69,69,,,69,69,69,69,69,,,69,69,69,69,,,,69,69,,69,,69,69,,,69,69', +',,,,,69,69,69,69,69,69,69,,,,69,,,,,,,,,,,,,,,,,,,,,,,,,,,,69,,,,69', +',69,223,69,,223,223,223,223,223,223,223,223,223,223,,,223,223,223,223', +'223,,,223,223,223,223,,,,223,223,,223,,223,223,,,223,223,,,,,,223,223', +'223,223,223,223,223,,,,223,,,,,,,,,,,,,,,,,,,,,,,,,,,,223,,,,223,,223', +'118,223,,118,118,118,118,118,118,118,118,118,118,,,118,118,118,118,118', +',,118,118,118,118,,,,118,118,,118,,118,118,,,118,118,,,,,,118,118,118', +'118,118,118,118,,,,118,,,,,,,,,,,,,,,,,,,,,,,,,,,,118,,,,118,,118,74', +'118,,74,74,74,74,74,74,74,74,74,74,,,74,74,74,74,74,,,74,74,74,74,,', +',74,74,,74,,74,74,,,74,74,74,,,,,74,74,74,74,74,74,74,,,,74,,,,,,,,', +',,,,,,,,,,,,,,,,,,,74,,,,74,,74,168,74,,168,168,168,168,168,168,168', +'168,168,168,,,168,168,168,168,168,,,168,168,168,168,,,,168,168,,168', +',168,168,,,168,168,168,,,,,168,168,168,168,168,168,168,,,,168,,,,,,', +',,,,,,,,,,,,,,,,,,,,,168,,,,168,,168,0,168,,0,0,0,0,0,0,0,0,0,0,,,0', +'0,0,0,0,,,0,0,0,0,,,,0,0,,0,,0,0,,,0,0,0,,,,,0,0,0,0,0,0,0,,,,0,,,,', +',,,,,,,,,,,,,,,,,,,,,,,0,0,0,,0,,0,124,0,,124,124,124,124,124,124,124', +'124,124,124,,,124,124,124,124,124,,,124,124,124,124,,,,124,124,,124', +',124,124,,,124,124,,,,,,124,124,124,124,124,124,124,,,,124,,,,,,,,,', +',,,,,,,,,,,,,,,,,,124,,,,124,,124,152,124,,152,152,152,152,152,152,152', +'152,152,152,,,152,152,152,152,152,,,152,152,152,152,,,,152,152,,152', +',152,152,,,152,152,,,,,,152,152,152,152,152,152,152,,,,152,,,,,,,,,', +',,,,,,,,,,,,,,,,,,152,,,,152,,152,136,152,,136,136,136,136,136,136,136', +'136,136,136,,,136,136,136,136,136,,,136,136,136,136,,,,136,136,,136', +',136,136,,,136,136,,,,,,136,136,136,136,136,136,136,,,,136,,,,,,,,,', +',,,,,,,,,,,,,,,,,,136,,,,136,,136,117,136,,117,117,117,117,117,117,117', +'117,117,117,,,117,117,117,117,117,,,117,117,117,117,,,,117,117,,117', +',117,117,,,117,117,,,,,,117,117,117,117,117,117,117,,,,117,,,,,,,,,', +',,,,,,,,,,,,,,,,,,117,,,,117,,117,134,117,,134,134,134,134,134,134,134', +'134,134,134,,,134,134,134,134,134,,,134,134,134,134,,,,134,134,,134', +',134,134,,,134,134,134,,,,,134,134,134,134,134,134,134,,,,134,,,,,,', +',,,,,,,,,,,,,,,,,,,,,134,,,,134,,134,82,134,,82,82,82,82,82,82,82,82', +'82,82,,,82,82,82,82,82,,,82,82,82,82,,,,82,82,,82,,82,82,,,82,82,,,', +',,82,82,82,82,82,82,82,,,,82,,,,,,,,,,,,,,,,,,,,,,,,,,,,82,,,,82,,82', +'131,82,,131,131,131,131,131,131,131,131,131,131,,,131,131,131,131,131', +',,131,131,131,131,,,,131,131,,131,,131,131,,,131,131,,,,,,131,131,131', +'131,131,131,131,,,,131,,,,,,,,,,,,,,,,,,,,,,,,,,,,131,,,,131,,131,128', +'131,,128,128,128,128,128,128,128,128,128,128,,,128,128,128,128,128,', +',128,128,128,128,,,,128,128,,128,,128,128,,,128,128,,,,,,128,128,128', +'128,128,128,128,,,,128,,,,,,,,,,,,,,,,,,,,,,,,,,,,128,,,,128,,128,127', +'128,,127,127,127,127,127,127,127,127,127,127,,,127,127,127,127,127,', +',127,127,127,127,,,,127,127,,127,,127,127,,,127,127,,,,,,127,127,127', +'127,127,127,127,,,,127,,,,,,,,,,,,,,,,,,,,,,,,,,,,127,,,,127,,127,126', +'127,,126,126,126,126,126,126,126,126,126,126,,,126,126,126,126,126,', +',126,126,126,126,,,,126,126,,126,,126,126,,,126,126,,,,,,126,126,126', +'126,126,126,126,,,,126,,,,,,,,,,,,,,,,,,,,,,,,,,,,126,,,,126,,126,93', +'126,,93,93,93,93,93,93,93,93,93,93,,,93,93,93,93,93,,,93,93,93,93,,', +',93,93,,93,,93,93,,,93,93,,,,,,93,93,93,93,93,93,93,,,,93,,,,,,,,,,', +',,,,,,,,,,,,,,,,,93,,,,93,,93,94,93,,94,94,94,94,94,94,94,94,94,94,', +',94,94,94,94,94,,,94,94,94,94,,,,94,94,,94,,94,94,,,94,94,,,,,,94,94', +'94,94,94,94,94,,,,94,,,,,,,,,,,,,,,,,,,,,,,,,,,,94,,,,94,,94,95,94,', +'95,95,95,95,95,95,95,95,95,95,,,95,95,95,95,95,,,95,95,95,95,,,,95,95', +',95,,95,95,,,95,95,,,,,,95,95,95,95,95,95,95,,,,95,,,,,,,,,,,,,,,,,', +',,,,,,,,,,95,,,,95,,95,96,95,,96,96,96,96,96,96,96,96,96,96,,,96,96', +'96,96,96,,,96,96,96,96,,,,96,96,,96,,96,96,,,96,96,,,,,,96,96,96,96', +'96,96,96,,,,96,,,,,,,,,,,,,,,,,,,,,,,,,,,,96,,,,96,,96,97,96,,97,97', +'97,97,97,97,97,97,97,97,,,97,97,97,97,97,,,97,97,97,97,,,,97,97,,97', +',97,97,,,97,97,,,,,,97,97,97,97,97,97,97,,,,97,,,,,,,,,,,,,,,,,,,,,', +',,,,,,97,,,,97,,97,123,97,,123,123,123,123,123,123,123,123,123,123,', +',123,123,123,123,123,,,123,123,123,123,,,,123,123,,123,,123,123,,,123', +'123,,,,,,123,123,123,123,123,123,123,,,,123,,,,,,,,,,,,,,,,,,,,,,,,', +',,,123,,,,123,,123,99,123,,99,99,99,99,99,99,99,99,99,99,,,99,99,99', +'99,99,,,99,99,99,99,,,,99,99,,99,,99,99,,,99,99,,,,,,99,99,99,99,99', +'99,99,,,,99,,,,,,,,,,,,,,,,,,,,,,,,,,,,99,,,,99,,99,100,99,,100,100', +'100,100,100,100,100,100,100,100,,,100,100,100,100,100,,,100,100,100', +'100,,,,100,100,,100,,100,100,,,100,100,,,,,,100,100,100,100,100,100', +'100,,,,100,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,,,,100,,100,101,100,,101,101', +'101,101,101,101,101,101,101,101,,,101,101,101,101,101,,,101,101,101', +'101,,,,101,101,,101,,101,101,,,101,101,,,,,,101,101,101,101,101,101', +'101,,,,101,,,,,,,,,,,,,,,,,,,,,,,,,,,,101,,,,101,,101,102,101,,102,102', +'102,102,102,102,102,102,102,102,,,102,102,102,102,102,,,102,102,102', +'102,,,,102,102,,102,,102,102,,,102,102,,,,,,102,102,102,102,102,102', +'102,,,,102,,,,,,,,,,,,,,,,,,,,,,,,,,,,102,,,,102,,102,116,102,,116,116', +'116,116,116,116,116,116,116,116,,,116,116,116,116,116,,,116,116,116', +'116,,,,116,116,,116,,116,116,,,116,116,,,,,,116,116,116,116,116,116', +'116,,,,116,,,,,,,,,,,,,,,,,,,,,,,,,,,,116,,,,116,,116,104,116,,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', +'104,,,,104,,,,,,,,,,,,,,,,,,,,,,,,,,,,104,,,,104,,104,105,104,,105,105', +'105,105,105,105,105,105,105,105,,,105,105,105,105,105,,,105,105,105', +'105,,,,105,105,,105,,105,105,,,105,105,,,,,,105,105,105,105,105,105', +'105,,,,105,,,,,,,,,,,,,,,,,,,,,,,,,,,,105,,,,105,,105,106,105,,106,106', +'106,106,106,106,106,106,106,106,,,106,106,106,106,106,,,106,106,106', +'106,,,,106,106,,106,,106,106,,,106,106,,,,,,106,106,106,106,106,106', +'106,,,,106,,,,,,,,,,,,,,,,,,,,,,,,,,,,106,,,,106,,106,107,106,,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,108,107,,108,108', +'108,108,108,108,108,108,108,108,,,108,108,108,108,108,,,108,108,108', +'108,,,,108,108,,108,,108,108,,,108,108,,,,,,108,108,108,108,108,108', +'108,,,,108,,,,,,,,,,,,,,,,,,,,,,,,,,,,108,,,,108,,108,109,108,,109,109', +'109,109,109,109,109,109,109,109,,,109,109,109,109,109,,,109,109,109', +'109,,,,109,109,,109,,109,109,,,109,109,,,,,,109,109,109,109,109,109', +'109,,,,109,,,,,,,,,,,,,,,,,,,,,,,,,,,,109,,,,109,,109,125,109,,125,125', +'125,125,125,125,125,125,125,125,,,125,125,125,125,125,,,125,125,125', +'125,,,,125,125,,125,,125,125,,,125,125,,,,,,125,125,125,125,125,125', +'125,,,,125,,,,,,,,,,,,,,,,,,,,,,,,,,,,125,,,,125,,125,111,125,,111,111', +'111,111,111,111,111,111,111,111,,,111,111,111,111,111,,,111,111,111', +'111,,,,111,111,,111,,111,111,,,111,111,,,,,,111,111,111,111,111,111', +'111,,,,111,,,,,,,,,,,,,,,,,,,,,,,,,,,,111,,,,111,,111,112,111,,112,112', +'112,112,112,112,112,112,112,112,,,112,112,112,112,112,,,112,112,112', +'112,,,,112,112,,112,,112,112,,,112,112,,,,,,112,112,112,112,112,112', +'112,,,,112,,,,,,,,,,,,,,,,,,,,,,,,,,,,112,,,,112,,112,113,112,,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,,,,113,,113,114,113,,114,114', +'114,114,114,114,114,114,114,114,,,114,114,114,114,114,,,114,114,114', +'114,,,,114,114,,114,,114,114,,,114,114,,,,,,114,114,114,114,114,114', +'114,,,,114,,,,,,,,,,,,,,,,,,,,,,,,,,,,114,,,,114,,114,115,114,,115,115', +'115,115,115,115,115,115,115,115,,,115,115,115,115,115,,,115,115,115', +'115,,,,115,115,,115,,115,115,,,115,115,,,,,,115,115,115,115,115,115', +'115,,,,115,,,,,,,,,,,,,,,,,,,,,,,,,,,,115,,,,115,,115,103,115,,103,103', +'103,103,103,103,103,103,103,103,,,103,103,103,103,103,,,103,103,103', +'103,,,,103,103,,103,,103,103,,,103,103,,,,,,103,103,103,103,103,103', +'103,217,,217,103,,,,61,61,61,61,61,61,61,61,61,61,,,,,,,,,217,,61,61', +',,103,,217,,103,,103,,103,,,217,61,,,,,,217,217,217,217,217,217,217', +'217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217', +'217,217,217,217,217,217,217,,217,217,278,,278,,,217,,,61,,61,,61,,,', +',,,,,,,,,278,,,,,,,,278,,,,,,,,,278,,,,,,,278,278,278,278,278,278,278', +'278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278', +'278,278,278,278,278,278,,,278,278,,,,,,278,1,1,1,1,1,1,1,1,1,1,,,,,', +',,,,,1,1,,,,,,,,,,,,,,,1,,,,284,,284,,,,,,,,,,,,,,,,,,,,,,,284,,,,,', +',,284,,,,,,,,,284,,1,,1,,1,284,284,284,284,284,284,284,284,284,284,284', +'284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284', +'284,284,,,284,284,153,,153,,,284,,,,,,,,,,,,,,,,,,,,153,,,,,,,,153,', +',,,,,,,153,,,,,,,153,153,153,153,153,153,153,153,153,153,153,153,153', +'153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153', +'153,,153,153,187,,187,,,,,,,,,,,,,,,,,,,,,,,187,,,,,,,,187,,,,,,,,,187', +',,,,,,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187', +'187,187,187,187,187,187,187,187,187,187,187,187,187,187,,,187,187,175', +',175,,,,,,,,,,,,,,,,,,,,,,,175,,,,,,,,175,,,,,,,,,175,,,,,,,175,175', +'175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175', +'175,175,175,175,175,175,175,175,175,175,175,,,175,175,280,,280,,,,,', +',,,,,,,,,,,,,,,,,280,,,,,,,,280,,,,,,,,,280,,,,,,,280,280,280,280,280', +'280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280', +'280,280,280,280,280,280,280,280,,,280,280,279,,279,,,,,,,,,,,,,,,,,', +',,,,,279,,,,,,,,279,,,,,,,,,279,,,,,,,279,279,279,279,279,279,279,279', +'279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279', +'279,279,279,279,279,,,279,279,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,227,,227,,,,,,,,,,,,,,,,,,,,,,,227,,,,,,,,227', +',,,,,,,,227,,,,,,,227,227,227,227,227,227,227,227,227,227,227,227,227', +'227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227', +',,227,227,169,,169,,,,,,,,,,,,,,,,,,,,,,,169,,,,,,,,169,,,,,,,,,169', +',,,,,,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169', +'169,169,169,169,169,169,169,169,169,169,169,169,169,169,,,169,169,150', +',150,,,,,,,,,,,,,,,,,,,,,,,150,,,,,,,,150,,,,,,,150,,150,,,,,,,150,150', +'150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150', +'150,150,150,150,150,150,150,150,150,150,150,,,150,150,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,262,,262,,,,,,,,,,,,,,,,,,,,,,,262,,,,,,,,262,,,,,,,,,262,,', +',,,,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262', +'262,262,262,262,262,262,262,262,262,262,262,262,262,262,,,262,262,261', +',261,,,,,,,,,,,,,,,,,,,,,,,261,,,,,,,,261,,,,,,,,,261,,,,,,,261,261', +'261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261', +'261,261,261,261,261,261,261,261,261,261,261,,,261,261,260,,260,,,,,', +',,,,,,,,,,,,,,,,,260,,,,,,,,260,,,,,,,,,260,,,,,,,260,260,260,260,260', +'260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260', +'260,260,260,260,260,260,260,260,,,260,260,259,,259,,,,,,,,,,,,,,,,,', +',,,,,259,,,,,,,,259,,,,,,,,,259,,,,,,,259,259,259,259,259,259,259,259', +'259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259', +'259,259,259,259,259,,,259,259,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,21,,21,,,,,,,,,,,', +',,,,,,,,,,,21,,,,,,,,21,,,,,,,,,21,,,,,,,21,21,21,21,21,21,21,21,21', +'21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,,,21', +'21,146,,146,,,,,,,,,,,,,,,,,,,,,,,146,,,,,,,,146,,,,,,,146,,146,,,,', +',,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146', +'146,146,146,146,146,146,146,146,146,146,146,146,146,,,146,146,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,91,,195,195,,,,,91,,,,,,,,,91,,', +',,,,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91', +'91,91,91,91,91,91,91,91,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,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,201,,,,,,,,201', +',,,,,,,,201,,,,,,,201,201,201,201,201,201,201,201,201,201,201,201,201', +'201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201', +'272,,,,,,,,,272,,,,,,,272,272,272,272,272,272,272,272,272,272,272,272', +'272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272', +'272,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,271,,,,,,,,,271,,,,,,,271,271,271,271,271,271,271,271,271,271', +'271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271', +'271,271,271,166,,,,,,,,,166,,,,,,,166,166,166,166,166,166,166,166,166', +'166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166', +'166,166,166,166,188,,,,,,,,,188,,,,,,,188,188,188,188,188,188,188,188', +'188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188', +'188,188,188,188,188,164,,,,,,,,,164,,,,,,,164,164,164,164,164,164,164', +'164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164', +'164,164,164,164,164,164,184,,,,,,,184,184,184,184,184,184,184,184,184', +'184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184', +'184,184,184,184,212,,,,,,,212,212,212,212,212,212,212,212,212,212,212', +'212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212', +'212,212,192,,,,,,,192,192,192,192,192,192,192,192,192,192,192,192,192', +'192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192', +'189,,,,,,,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189', +'189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,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' ] + racc_action_check = arr = Array.new(8814, nil) idx = 0 clist.each do |str| str.split(',', -1).each do |i| @@ -589,361 +634,342 @@ def on_error(error_token_id, error_value, value_stack) end racc_action_pointer = [ - -2, 80, nil, nil, nil, 162, 244, nil, nil, 326, - 408, 40, nil, nil, 572, nil, nil, nil, 116, nil, - nil, nil, nil, 736, nil, 818, 190, nil, nil, -45, - nil, nil, 6903, 1146, nil, nil, nil, nil, nil, 1228, - nil, nil, 1310, nil, nil, nil, 1392, 45, 141, nil, - 1638, nil, nil, 307, 1802, 1884, nil, nil, nil, 1966, - 2048, 225, 2212, 6312, nil, nil, nil, 215, 7985, -20, - 6671, 7763, 2786, 334, 72, 3032, 326, 351, -25, 3360, - -3, 3524, 3606, 3688, 3770, 3852, 3934, 4016, 4098, nil, - 4180, 4262, 4344, nil, 4426, 4508, 4590, 4672, 4754, 4836, - 4918, -13, 5082, 5164, 5246, 5328, 5410, 5492, 5574, 5656, - 5738, 5820, 5902, 5984, 6066, 6148, 6230, 2294, 484, 7273, - 306, 6592, 399, 6434, 3278, 224, 304, nil, -18, nil, - -13, -11, 379, nil, nil, 127, 52, 2622, nil, 2540, - 2458, 2, 7421, -59, 75, nil, 2130, 7901, 339, 1474, - nil, nil, 316, nil, nil, 5, nil, 7199, 7943, 7569, - 497, 1245, 7642, 989, 1235, 7859, 825, 1317, 743, 1166, - 317, 8105, 1084, 235, 7811, 14, 74, 8015, 1071, 192, - 8075, 1153, 846, 8135, 661, 764, 8045, 907, 682, 579, - 600, 415, 1255, 1064, 1720, nil, 36, 2376, 82, 229, - 31, nil, 5000, 3196, 60, 142, nil, 6357, 402, 7715, - nil, 114, -9, 320, 28, nil, nil, 105, 2950, nil, - 7347, 6977, 209, 239, 42, nil, 654, nil, nil, 6829, - 7495, nil, nil, 900, 1556, nil, nil, nil, nil, 2704, - nil, nil, 0, nil, 7125, -1, 226, 291, nil, 3442, - nil, nil, 6513, 356, 110, 3114, 70, nil, nil, 2868, - nil, nil, 143, 153, 982, nil, 6750, nil, 7051, nil, - nil, 119, 490, nil, 274 ] + 3238, 6519, nil, 178, 268, 221, nil, 448, 171, nil, + nil, nil, 78, nil, nil, 115, 808, nil, -49, 988, + nil, 7890, -71, nil, nil, 65, nil, nil, nil, nil, + 70, nil, nil, nil, nil, 44, nil, 1528, nil, nil, + nil, nil, 1618, nil, nil, nil, 1708, nil, 1798, nil, + 1888, 70, nil, 2068, nil, 2158, nil, 2248, nil, 2338, + nil, 6354, nil, 218, 2608, nil, nil, 2698, nil, 2788, + nil, 159, 129, nil, 3058, 127, 64, 189, 7807, 167, + 7392, 126, 3778, 108, nil, 220, nil, nil, 88, nil, + nil, 8110, nil, 4228, 4318, 4408, 4498, 4588, 88, 4768, + 4858, 4948, 5038, 6298, 5218, 5308, 5398, 5488, 5578, 5668, + 231, 5848, 5938, 6028, 6118, 6208, 5128, 3598, 2968, nil, + 2428, 358, nil, 4678, 3328, 5758, 4138, 4048, 3958, 134, + 159, 3868, 186, nil, 3688, -2, 3508, nil, nil, nil, + 127, 58, nil, 439, 532, 529, 7973, 509, nil, nil, + 7309, 419, 3418, 6645, -42, 204, 89, 73, -60, -42, + 264, nil, 284, nil, 8548, -2, 8456, nil, 3148, 7226, + nil, nil, 97, 100, 152, 6811, nil, nil, nil, nil, + nil, 8733, 1178, 117, 8585, 1088, 259, 6728, 8502, 8696, + 998, 349, 8659, 638, -25, 8056, 368, 1465, 211, 278, + 1375, 8272, 818, 1538, 8164, 458, 1358, 548, 1448, 728, + 908, 442, 8622, 1268, 329, nil, nil, 6350, nil, 165, + 28, 8218, 114, 2878, 116, nil, 1, 7143, 35, 2518, + nil, 1978, nil, 1438, 1348, 120, nil, 7, 84, nil, + 150, -22, -24, nil, 103, nil, -2, nil, 1258, 1168, + 8364, nil, 1078, 214, nil, nil, 898, 718, 628, 7724, + 7641, 7558, 7475, 228, nil, nil, nil, nil, nil, nil, + nil, 8410, 8318, 7060, 169, nil, nil, 538, 6433, 6977, + 6894, nil, -51, 200, 6562, nil, nil, nil, nil ] racc_action_default = [ - -1, -152, -37, -24, -13, -152, -152, -38, -14, -152, - -152, -152, -113, -96, -152, -39, -25, -15, -152, -40, - -33, -26, -16, -2, -95, -91, -152, -34, -17, -3, - -46, -18, -4, -121, -97, -31, -29, -19, -8, -152, - -98, -93, -152, -30, -20, -9, -152, -152, -107, -99, - -152, -32, -21, -10, -152, -152, -35, -22, -11, -152, - -152, -111, -152, -152, -36, -23, -12, -51, -87, -53, - -152, -129, -121, -52, -152, -152, -7, -92, -152, -91, - -152, -6, -152, -152, -152, -152, -152, -152, -152, -55, - -152, -152, -152, -54, -152, -152, -152, -152, -152, -152, - -152, -152, -152, -152, -152, -152, -152, -152, -152, -152, - -152, -152, -152, -152, -152, -152, -152, -152, -152, -122, - -10, -152, -49, -152, -121, -152, -112, -44, -152, -108, - -152, -152, -50, -103, -104, -152, -152, -152, -100, -121, - -152, -47, -45, -152, -127, -101, -121, -86, -48, -152, - -28, -27, -152, 275, -90, -152, -94, -5, -88, -84, - -75, -64, -85, -76, -65, -150, -77, -66, -78, -67, - -56, -79, -68, -57, -151, -133, -152, -80, -69, -58, - -81, -70, -59, -82, -71, -60, -83, -72, -61, -73, - -62, -74, -63, -152, -152, -120, -152, -152, -152, -152, - -152, -106, -152, -152, -114, -152, -102, -152, -152, -41, - -130, -152, -152, -152, -152, -117, -89, -152, -152, -132, - -124, -123, -152, -152, -152, -139, -152, -110, -109, -42, - -43, -105, -115, -152, -152, -125, -116, -147, -149, -152, - -145, -143, -152, -134, -152, -8, -152, -152, -131, -152, - -140, -137, -152, -128, -152, -152, -152, -148, -144, -152, - -135, -118, -152, -152, -152, -126, -152, -146, -152, -119, - -138, -141, -152, -136, -142 ] + -1, -167, -21, -167, -167, -167, -22, -167, -167, -2, + -46, -23, -3, -31, -24, -160, -167, -98, -167, -167, + -29, -5, -167, -30, -33, -8, -32, -34, -9, -92, + -167, -35, -10, -99, -36, -167, -11, -167, -100, -37, + -27, -12, -167, -101, -28, -13, -167, -38, -167, -14, + -167, -115, -39, -167, -15, -167, -40, -127, -16, -167, + -97, -167, -117, -109, -167, -17, -18, -167, -94, -167, + -19, -167, -167, -20, -127, -167, -116, -49, -45, -167, + -167, -167, -7, -167, -158, -160, -162, -164, -167, -26, + -4, -139, -89, -167, -167, -167, -167, -167, -167, -167, + -167, -167, -167, -167, -167, -167, -167, -167, -167, -167, + -167, -167, -167, -167, -167, -167, -167, -167, -167, -57, + -167, -167, -56, -167, -167, -167, -167, -167, -167, -167, + -167, -167, -167, -102, -127, -167, -167, -106, -105, -119, + -167, -144, -91, -50, -47, -48, -167, -51, -103, -120, + -167, -53, -167, -128, -167, -52, -96, -167, -167, -167, + -167, -44, -109, -110, -54, -167, -55, -95, -127, -128, + 289, -156, -167, -135, -167, -6, -161, -157, -159, -163, + -25, -82, -71, -60, -83, -72, -61, -165, -88, -84, + -73, -62, -85, -74, -63, -166, -75, -64, -167, -76, + -65, -86, -77, -66, -87, -78, -67, -79, -68, -80, + -69, -58, -81, -70, -59, -93, -90, -167, -104, -167, + -118, -41, -167, -167, -167, -141, -167, -129, -167, -167, + -126, -167, -134, -167, -167, -167, -108, -167, -167, -140, + -167, -167, -167, -136, -142, -107, -121, -143, -167, -167, + -146, -145, -167, -167, -151, -155, -167, -167, -167, -130, + -131, -42, -43, -167, -111, -112, -114, -123, -138, -137, + -122, -148, -147, -167, -167, -152, -149, -167, -167, -132, + -133, -113, -153, -167, -167, -124, -154, -150, -125 ] racc_goto_table = [ - 23, 29, 120, 126, 149, 78, 134, 145, 127, 225, - 129, 18, 128, 212, 134, 152, 125, 176, 219, 224, - 245, 258, 257, nil, nil, nil, 77, nil, nil, 81, - nil, nil, nil, nil, nil, 250, nil, nil, nil, nil, + 9, 140, 219, 21, 137, 84, 77, 78, 75, 76, + 80, 254, 82, 86, 160, 222, 5, 253, 90, 21, + 173, 177, 91, 12, 215, 85, 270, 149, 87, nil, + 137, nil, 148, 161, nil, 264, 240, 265, 275, 88, + 143, nil, 18, nil, nil, 144, nil, nil, nil, 145, + 81, 146, 149, 147, 137, 137, 150, 148, 151, nil, + 153, nil, 155, 281, nil, nil, nil, 164, 156, 157, + 165, nil, 166, 244, nil, 178, nil, 142, nil, nil, + nil, 198, nil, 179, nil, 175, nil, nil, 82, nil, + nil, nil, nil, nil, nil, nil, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 238, 199, 200, 201, 202, 203, 204, + 205, 206, 171, 207, 208, 176, 209, 210, 211, 212, + 213, 214, 161, 149, 217, 137, 137, nil, 148, 221, + nil, nil, 220, 157, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 227, nil, nil, nil, nil, + 237, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, 216, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, 225, nil, + nil, nil, nil, nil, nil, nil, 255, nil, nil, 137, + nil, nil, nil, nil, nil, 161, nil, 161, nil, nil, + nil, nil, nil, nil, nil, nil, 243, nil, nil, nil, + nil, nil, nil, 255, nil, nil, 250, nil, nil, 257, + nil, nil, 259, 161, 260, 263, 261, 262, 237, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, 197, nil, 198, nil, 155, - 143, 144, nil, nil, nil, nil, nil, nil, nil, nil, - 150, nil, 145, 134, nil, nil, 81, 81, 134, 134, - 77, nil, 208, nil, nil, nil, nil, nil, nil, 213, - nil, 205, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 204, nil, 120, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 193, nil, - nil, 150, nil, 150, nil, nil, nil, nil, 199, nil, + nil, 271, 272, nil, nil, 273, nil, nil, nil, 278, + 279, 280, nil, nil, 247, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 81, 81, nil, nil, nil, nil, nil, - 214, 145, 193, nil, nil, nil, nil, 134, 134, 127, - 127, 227, 228, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 205, nil, - nil, nil, nil, nil, nil, nil, 264, nil, nil, nil, - nil, 246, nil, nil, nil, nil, nil, nil, 223, 134, - 272, nil, nil, 205, nil, nil, nil, nil, 193, nil, - nil, nil, nil, 193, 81, 134, 262, nil, nil, nil, - nil, nil, nil, 81, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 253, 254, nil, nil, 67, nil, - 256, nil, 68, 69, nil, nil, 70, 71, nil, nil, - 263, 73, 150, 81, 81, nil, 81, nil, nil, nil, - nil, nil, nil, 81, nil, 271, 150, nil, nil, nil, - 119, 81, nil, 274, 81, nil, 121, nil, nil, 122, - nil, nil, nil, 123, nil, nil, nil, 132, nil, nil, - nil, 141, 142, nil, nil, nil, nil, nil, nil, 147, - 148, nil, nil, nil, nil, nil, nil, nil, nil, 119, - nil, nil, nil, nil, nil, nil, nil, nil, 157, 158, - 159, 160, 161, 162, 163, 164, nil, 165, 166, 167, - nil, 168, 169, 170, 171, 172, 173, 174, nil, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, nil, nil, nil, nil, nil, - nil, 119, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 207, nil, 119, 209, nil, nil, - nil, nil, nil, 119, nil, nil, nil, nil, nil, nil, + 284, nil, 286, 268, 269, 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, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 220, 221, nil, nil, nil, nil, nil, nil, nil, 229, - 230, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, 244, nil, nil, nil, nil, - nil, nil, nil, 252, 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, 266, nil, nil, nil, 268 ] + nil, nil, nil, nil, nil, 282, 283 ] racc_goto_check = [ - 2, 3, 7, 31, 22, 26, 11, 30, 21, 40, - 24, 1, 33, 36, 11, 35, 7, 37, 38, 39, - 5, 41, 43, nil, nil, nil, 3, nil, nil, 2, - nil, nil, nil, nil, nil, 40, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, 22, nil, 22, nil, 26, - 3, 3, nil, nil, nil, nil, nil, nil, nil, nil, - 2, nil, 30, 11, nil, nil, 2, 2, 11, 11, - 3, nil, 35, nil, nil, nil, nil, nil, nil, 35, - nil, 31, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 7, nil, 7, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 2, nil, - nil, 2, nil, 2, nil, nil, nil, nil, 2, nil, + 2, 38, 36, 5, 10, 43, 5, 5, 6, 31, + 5, 41, 2, 45, 33, 39, 1, 40, 2, 5, + 37, 42, 5, 3, 26, 44, 8, 35, 46, nil, + 10, nil, 30, 22, nil, 24, 36, 24, 41, 3, + 5, nil, 4, nil, nil, 5, nil, nil, nil, 5, + 4, 5, 35, 5, 10, 10, 5, 30, 5, nil, + 5, nil, 5, 24, nil, nil, nil, 5, 6, 31, + 5, nil, 5, 39, nil, 43, nil, 4, nil, nil, + nil, 38, nil, 45, nil, 5, nil, nil, 2, nil, + nil, nil, nil, nil, nil, nil, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 33, 5, 5, 5, 5, 5, 5, + 5, 5, 4, 5, 5, 4, 5, 5, 5, 5, + 5, 5, 22, 35, 5, 10, 10, nil, 30, 5, + nil, nil, 6, 31, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 5, nil, nil, nil, nil, + 2, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, 4, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, 4, nil, + nil, nil, nil, nil, nil, nil, 22, nil, nil, 10, + nil, nil, nil, nil, nil, 22, nil, 22, nil, nil, + nil, nil, nil, nil, nil, nil, 4, nil, nil, nil, + nil, nil, nil, 22, nil, nil, 5, nil, nil, 2, + nil, nil, 5, 22, 5, 2, 5, 5, 2, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 2, 2, nil, nil, nil, nil, nil, - 3, 30, 2, nil, nil, nil, nil, 11, 11, 21, - 21, 24, 24, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 31, nil, - nil, nil, nil, nil, nil, nil, 22, nil, nil, nil, - nil, 7, nil, nil, nil, nil, nil, nil, 3, 11, - 22, nil, nil, 31, nil, nil, nil, nil, 2, nil, - nil, nil, nil, 2, 2, 11, 7, nil, nil, nil, - nil, nil, nil, 2, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 3, 3, nil, nil, 4, nil, - 3, nil, 4, 4, nil, nil, 4, 4, nil, nil, - 3, 4, 2, 2, 2, nil, 2, nil, nil, nil, - nil, nil, nil, 2, nil, 3, 2, nil, nil, nil, - 4, 2, nil, 3, 2, nil, 4, nil, nil, 4, - nil, nil, nil, 4, nil, nil, nil, 4, nil, nil, - nil, 4, 4, nil, nil, nil, nil, nil, nil, 4, - 4, nil, nil, nil, nil, nil, nil, nil, nil, 4, - nil, nil, nil, nil, nil, nil, nil, nil, 4, 4, - 4, 4, 4, 4, 4, 4, nil, 4, 4, 4, - nil, 4, 4, 4, 4, 4, 4, 4, nil, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, nil, nil, nil, nil, nil, - nil, 4, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, 4, nil, 4, 4, nil, nil, - nil, nil, nil, 4, nil, nil, nil, nil, nil, nil, + nil, 5, 5, nil, nil, 5, nil, nil, nil, 5, + 5, 5, nil, nil, 4, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + 5, nil, 2, 4, 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, nil, - 4, 4, nil, nil, nil, nil, nil, nil, nil, 4, - 4, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, 4, nil, nil, nil, nil, - nil, nil, nil, 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, 4, nil, nil, nil, 4 ] + nil, nil, nil, nil, nil, 4, 4 ] racc_goto_pointer = [ - nil, 11, 0, 1, 237, -198, nil, -31, nil, nil, - nil, -47, nil, nil, nil, nil, nil, nil, nil, nil, - nil, -40, -66, nil, -38, nil, -20, nil, nil, nil, - -54, -44, nil, -36, nil, -57, -131, -84, -158, -179, - -189, -221, nil, -220, nil ] + nil, 16, 0, 23, 42, 3, 7, nil, -220, nil, + -21, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, -30, nil, -200, nil, -105, nil, nil, nil, + -19, 8, nil, -49, nil, -24, -132, -61, -29, -125, + -209, -215, -62, -10, 10, -2, 13 ] racc_goto_default = [ - nil, nil, 75, 76, 32, 38, 45, 53, 58, 66, - 4, 8, 17, 22, 28, 31, 37, 44, 52, 57, - 65, 3, nil, 13, nil, 26, nil, 34, 40, 49, - 138, 61, 133, nil, 12, 118, nil, nil, nil, nil, - nil, 241, 242, 237, 238 ] + nil, nil, 231, nil, nil, 169, 25, 28, 32, 36, + 41, 45, 49, 54, 58, 65, 66, 70, 73, 2, + 6, 11, 14, 17, 163, 22, 29, 33, 38, 43, + 133, 51, 138, nil, 62, 139, 154, nil, nil, nil, + nil, nil, 15, nil, nil, nil, nil ] racc_reduce_table = [ 0, 0, :racc_error, - 0, 90, :_reduce_1, - 1, 90, :_reduce_2, - 1, 90, :_reduce_3, - 1, 92, :_reduce_4, - 3, 92, :_reduce_5, - 2, 92, :_reduce_6, - 2, 92, :_reduce_7, - 1, 93, :_reduce_none, - 1, 93, :_reduce_none, - 1, 94, :_reduce_none, - 1, 94, :_reduce_none, - 1, 94, :_reduce_none, - 1, 94, :_reduce_none, - 1, 94, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 95, :_reduce_none, - 1, 91, :_reduce_none, - 1, 91, :_reduce_none, - 1, 111, :_reduce_none, - 1, 111, :_reduce_none, - 1, 112, :_reduce_29, - 1, 112, :_reduce_30, - 1, 112, :_reduce_31, - 1, 112, :_reduce_32, - 1, 112, :_reduce_33, - 1, 112, :_reduce_34, - 1, 112, :_reduce_35, - 1, 112, :_reduce_36, - 1, 112, :_reduce_37, - 1, 112, :_reduce_38, - 1, 112, :_reduce_39, - 1, 112, :_reduce_40, - 3, 101, :_reduce_41, - 3, 113, :_reduce_42, - 3, 113, :_reduce_43, - 1, 113, :_reduce_44, - 2, 105, :_reduce_45, - 1, 110, :_reduce_46, - 2, 99, :_reduce_47, - 2, 99, :_reduce_48, - 2, 99, :_reduce_49, - 2, 99, :_reduce_50, - 2, 99, :_reduce_51, - 2, 99, :_reduce_52, - 2, 99, :_reduce_53, - 2, 99, :_reduce_54, - 2, 99, :_reduce_55, - 3, 99, :_reduce_56, - 3, 99, :_reduce_57, - 3, 99, :_reduce_58, - 3, 99, :_reduce_59, - 3, 99, :_reduce_60, - 3, 99, :_reduce_61, - 3, 99, :_reduce_62, - 3, 99, :_reduce_63, - 3, 99, :_reduce_64, - 3, 99, :_reduce_65, - 3, 99, :_reduce_66, - 3, 99, :_reduce_67, - 3, 99, :_reduce_68, - 3, 99, :_reduce_69, - 3, 99, :_reduce_70, - 3, 99, :_reduce_71, - 3, 99, :_reduce_72, - 3, 99, :_reduce_73, - 3, 99, :_reduce_74, - 3, 99, :_reduce_75, - 3, 99, :_reduce_76, - 3, 99, :_reduce_77, - 3, 99, :_reduce_78, - 3, 99, :_reduce_79, - 3, 99, :_reduce_80, - 3, 99, :_reduce_81, - 3, 99, :_reduce_82, - 3, 99, :_reduce_83, - 3, 99, :_reduce_84, - 3, 99, :_reduce_85, - 2, 99, :_reduce_86, - 2, 99, :_reduce_87, - 3, 99, :_reduce_88, - 4, 98, :_reduce_89, - 3, 98, :_reduce_90, - 0, 115, :_reduce_91, - 1, 115, :_reduce_92, - 1, 114, :_reduce_93, - 3, 114, :_reduce_94, - 1, 96, :_reduce_95, - 1, 96, :_reduce_96, - 1, 96, :_reduce_97, - 1, 96, :_reduce_98, - 1, 96, :_reduce_99, - 2, 96, :_reduce_100, - 2, 96, :_reduce_101, - 2, 119, :_reduce_102, - 1, 119, :_reduce_103, - 1, 119, :_reduce_104, - 3, 121, :_reduce_105, - 3, 117, :_reduce_106, - 0, 122, :_reduce_107, - 1, 122, :_reduce_108, - 3, 122, :_reduce_109, - 3, 122, :_reduce_110, - 1, 97, :_reduce_111, - 2, 97, :_reduce_112, - 1, 97, :_reduce_113, - 3, 109, :_reduce_114, - 4, 120, :_reduce_115, - 4, 120, :_reduce_116, - 4, 123, :_reduce_117, - 6, 100, :_reduce_118, - 7, 100, :_reduce_119, - 3, 116, :_reduce_120, - 0, 124, :_reduce_121, - 1, 124, :_reduce_122, - 3, 124, :_reduce_123, - 3, 124, :_reduce_124, - 4, 103, :_reduce_125, - 6, 103, :_reduce_126, - 0, 125, :_reduce_127, - 3, 125, :_reduce_128, - 2, 104, :_reduce_129, - 3, 118, :_reduce_130, - 5, 106, :_reduce_131, - 4, 107, :_reduce_132, - 1, 126, :_reduce_133, - 3, 126, :_reduce_134, - 3, 127, :_reduce_135, - 5, 127, :_reduce_136, + 0, 96, :_reduce_1, + 1, 96, :_reduce_2, + 1, 96, :_reduce_3, + 2, 96, :_reduce_4, + 1, 98, :_reduce_5, + 3, 98, :_reduce_6, + 2, 98, :_reduce_7, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 3, 99, :_reduce_25, + 2, 99, :_reduce_26, + 1, 97, :_reduce_none, + 1, 97, :_reduce_none, + 1, 118, :_reduce_29, + 1, 118, :_reduce_30, + 1, 118, :_reduce_31, + 1, 118, :_reduce_32, + 1, 118, :_reduce_33, + 1, 118, :_reduce_34, + 1, 118, :_reduce_35, + 1, 118, :_reduce_36, + 1, 118, :_reduce_37, + 1, 118, :_reduce_38, + 1, 118, :_reduce_39, + 1, 118, :_reduce_40, + 3, 106, :_reduce_41, + 3, 119, :_reduce_42, + 3, 119, :_reduce_43, + 1, 119, :_reduce_44, + 2, 110, :_reduce_45, + 1, 117, :_reduce_46, + 2, 104, :_reduce_47, + 2, 104, :_reduce_48, + 2, 104, :_reduce_49, + 2, 104, :_reduce_50, + 2, 104, :_reduce_51, + 2, 104, :_reduce_52, + 2, 104, :_reduce_53, + 2, 104, :_reduce_54, + 2, 104, :_reduce_55, + 2, 104, :_reduce_56, + 2, 104, :_reduce_57, + 3, 104, :_reduce_58, + 3, 104, :_reduce_59, + 3, 104, :_reduce_60, + 3, 104, :_reduce_61, + 3, 104, :_reduce_62, + 3, 104, :_reduce_63, + 3, 104, :_reduce_64, + 3, 104, :_reduce_65, + 3, 104, :_reduce_66, + 3, 104, :_reduce_67, + 3, 104, :_reduce_68, + 3, 104, :_reduce_69, + 3, 104, :_reduce_70, + 3, 104, :_reduce_71, + 3, 104, :_reduce_72, + 3, 104, :_reduce_73, + 3, 104, :_reduce_74, + 3, 104, :_reduce_75, + 3, 104, :_reduce_76, + 3, 104, :_reduce_77, + 3, 104, :_reduce_78, + 3, 104, :_reduce_79, + 3, 104, :_reduce_80, + 3, 104, :_reduce_81, + 3, 104, :_reduce_82, + 3, 104, :_reduce_83, + 3, 104, :_reduce_84, + 3, 104, :_reduce_85, + 3, 104, :_reduce_86, + 3, 104, :_reduce_87, + 3, 104, :_reduce_88, + 2, 116, :_reduce_89, + 3, 103, :_reduce_90, + 2, 103, :_reduce_91, + 1, 120, :_reduce_92, + 3, 120, :_reduce_93, + 1, 121, :_reduce_none, + 2, 121, :_reduce_95, + 2, 115, :_reduce_96, + 1, 101, :_reduce_97, + 1, 101, :_reduce_98, + 1, 101, :_reduce_99, + 1, 101, :_reduce_100, + 1, 101, :_reduce_101, + 2, 101, :_reduce_102, + 2, 101, :_reduce_103, + 2, 125, :_reduce_104, + 1, 125, :_reduce_105, + 1, 125, :_reduce_106, + 3, 127, :_reduce_107, + 3, 123, :_reduce_108, + 0, 128, :_reduce_109, + 1, 128, :_reduce_110, + 3, 128, :_reduce_111, + 3, 128, :_reduce_112, + 4, 128, :_reduce_113, + 3, 128, :_reduce_114, + 1, 102, :_reduce_115, + 2, 102, :_reduce_116, + 1, 102, :_reduce_117, + 3, 114, :_reduce_118, + 2, 126, :_reduce_119, + 2, 126, :_reduce_120, + 3, 130, :_reduce_121, + 4, 130, :_reduce_122, + 4, 129, :_reduce_123, + 6, 105, :_reduce_124, + 7, 105, :_reduce_125, + 3, 122, :_reduce_126, + 0, 131, :_reduce_127, + 1, 131, :_reduce_128, + 2, 131, :_reduce_129, + 3, 131, :_reduce_130, + 3, 131, :_reduce_131, + 4, 131, :_reduce_132, + 4, 131, :_reduce_133, + 2, 131, :_reduce_134, + 3, 108, :_reduce_135, + 4, 108, :_reduce_136, 5, 108, :_reduce_137, - 7, 108, :_reduce_138, - 1, 128, :_reduce_139, - 2, 128, :_reduce_140, - 4, 129, :_reduce_141, - 5, 130, :_reduce_142, - 1, 131, :_reduce_143, - 2, 131, :_reduce_144, - 1, 132, :_reduce_145, - 3, 132, :_reduce_146, - 1, 133, :_reduce_147, - 2, 133, :_reduce_148, - 5, 102, :_reduce_149, - 3, 102, :_reduce_150, - 3, 102, :_reduce_151 ] - -racc_reduce_n = 152 - -racc_shift_n = 275 + 3, 132, :_reduce_138, + 2, 109, :_reduce_139, + 3, 124, :_reduce_140, + 3, 111, :_reduce_141, + 4, 112, :_reduce_142, + 4, 112, :_reduce_143, + 1, 133, :_reduce_144, + 3, 133, :_reduce_145, + 2, 134, :_reduce_146, + 3, 134, :_reduce_147, + 3, 134, :_reduce_148, + 5, 113, :_reduce_149, + 7, 113, :_reduce_150, + 1, 135, :_reduce_151, + 2, 135, :_reduce_152, + 3, 136, :_reduce_153, + 4, 136, :_reduce_154, + 1, 136, :_reduce_none, + 3, 137, :_reduce_156, + 2, 138, :_reduce_157, + 1, 139, :_reduce_158, + 2, 139, :_reduce_159, + 0, 140, :_reduce_160, + 2, 140, :_reduce_161, + 1, 141, :_reduce_162, + 2, 141, :_reduce_163, + 2, 107, :_reduce_164, + 3, 107, :_reduce_165, + 3, 107, :_reduce_166 ] + +racc_reduce_n = 167 + +racc_shift_n = 289 racc_token_table = { false => 0, :error => 1, :IF => 2, :ELSE => 3, - :THEN => 4, - :UNLESS => 5, - :NUMBER => 6, - :STRING => 7, - :REGEX => 8, - :TRUE => 9, - :FALSE => 10, - :YES => 11, - :NO => 12, - :ON => 13, - :OFF => 14, - :IDENTIFIER => 15, - :PROPERTY_ACCESS => 16, - :CODE => 17, - :PARAM => 18, + :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, + :CODE => 16, + :PARAM => 17, + :PARAM_SPLAT => 18, :NEW => 19, :RETURN => 20, :TRY => 21, @@ -954,68 +980,74 @@ def on_error(error_token_id, error_value, value_stack) :CONTINUE => 26, :FOR => 27, :IN => 28, - :WHILE => 29, - :SWITCH => 30, - :WHEN => 31, - :DELETE => 32, - :INSTANCEOF => 33, - :TYPEOF => 34, - :SUPER => 35, - :EXTENDS => 36, - :NEWLINE => 37, - :COMMENT => 38, - :JS => 39, - :UMINUS => 40, - :NOT => 41, - "!" => 42, - "!!" => 43, - "~" => 44, - "++" => 45, - "--" => 46, - "*" => 47, - "/" => 48, - "%" => 49, - "+" => 50, - "-" => 51, - "<<" => 52, - ">>" => 53, - ">>>" => 54, - "&" => 55, - "|" => 56, - "^" => 57, - "<=" => 58, - "<" => 59, - ">" => 60, - ">=" => 61, - "==" => 62, - "!=" => 63, - :IS => 64, - :ISNT => 65, - "&&" => 66, - "||" => 67, - :AND => 68, - :OR => 69, - "-=" => 70, - "+=" => 71, - "/=" => 72, - "*=" => 73, - "%=" => 74, - "." => 75, - :ASSIGN => 76, - "||=" => 77, - "&&=" => 78, - "\n" => 79, - ";" => 80, - "=>" => 81, - "," => 82, - "[" => 83, - "]" => 84, - "{" => 85, - "}" => 86, - "(" => 87, - ")" => 88 } - -racc_nt_base = 89 + :BY => 29, + :WHEN => 30, + :WHILE => 31, + :SWITCH => 32, + :LEADING_WHEN => 33, + :DELETE => 34, + :INSTANCEOF => 35, + :TYPEOF => 36, + :SUPER => 37, + :EXTENDS => 38, + :NEWLINE => 39, + :COMMENT => 40, + :JS => 41, + :INDENT => 42, + :OUTDENT => 43, + "?" => 44, + :UMINUS => 45, + :SPLAT => 46, + :NOT => 47, + "!" => 48, + "!!" => 49, + "~" => 50, + "++" => 51, + "--" => 52, + "*" => 53, + "/" => 54, + "%" => 55, + "+" => 56, + "-" => 57, + "<<" => 58, + ">>" => 59, + ">>>" => 60, + "&" => 61, + "|" => 62, + "^" => 63, + "<=" => 64, + "<" => 65, + ">" => 66, + ">=" => 67, + "==" => 68, + "!=" => 69, + :IS => 70, + :ISNT => 71, + "&&" => 72, + "||" => 73, + :AND => 74, + :OR => 75, + "-=" => 76, + "+=" => 77, + "/=" => 78, + "*=" => 79, + "%=" => 80, + "." => 81, + :ASSIGN => 82, + "||=" => 83, + "&&=" => 84, + "=>" => 85, + "\n" => 86, + ";" => 87, + "," => 88, + "[" => 89, + "]" => 90, + "{" => 91, + "}" => 92, + "(" => 93, + ")" => 94 } + +racc_nt_base = 95 racc_use_result_var = true @@ -1040,7 +1072,6 @@ def on_error(error_token_id, error_value, value_stack) "error", "IF", "ELSE", - "THEN", "UNLESS", "NUMBER", "STRING", @@ -1055,6 +1086,7 @@ def on_error(error_token_id, error_value, value_stack) "PROPERTY_ACCESS", "CODE", "PARAM", + "PARAM_SPLAT", "NEW", "RETURN", "TRY", @@ -1065,9 +1097,11 @@ def on_error(error_token_id, error_value, value_stack) "CONTINUE", "FOR", "IN", + "BY", + "WHEN", "WHILE", "SWITCH", - "WHEN", + "LEADING_WHEN", "DELETE", "INSTANCEOF", "TYPEOF", @@ -1076,7 +1110,11 @@ def on_error(error_token_id, error_value, value_stack) "NEWLINE", "COMMENT", "JS", + "INDENT", + "OUTDENT", + "\"?\"", "UMINUS", + "SPLAT", "NOT", "\"!\"", "\"!!\"", @@ -1115,9 +1153,9 @@ def on_error(error_token_id, error_value, value_stack) "ASSIGN", "\"||=\"", "\"&&=\"", + "\"=>\"", "\"\\n\"", "\";\"", - "\"=>\"", "\",\"", "\"[\"", "\"]\"", @@ -1129,9 +1167,8 @@ def on_error(error_token_id, error_value, value_stack) "Root", "Terminator", "Expressions", + "Block", "Expression", - "PureExpression", - "Statement", "Value", "Call", "Code", @@ -1146,12 +1183,13 @@ def on_error(error_token_id, error_value, value_stack) "For", "Switch", "Extends", + "Splat", + "Existence", "Comment", - "Then", "Literal", "AssignObj", "ParamList", - "CodeBody", + "Param", "Array", "Object", "Parenthetical", @@ -1160,12 +1198,14 @@ def on_error(error_token_id, error_value, value_stack) "Index", "AssignList", "Super", + "Arguments", "ArgList", "Catch", "ForVariables", "ForSource", "Whens", "When", + "IfBlock", "ElsIf", "ElsIfs", "ElseBody", @@ -1177,51 +1217,51 @@ def on_error(error_token_id, error_value, value_stack) # reduce 0 omitted -module_eval(<<'.,.,', 'grammar.y', 45) +module_eval(<<'.,.,', 'grammar.y', 46) def _reduce_1(val, _values, result) - result = Expressions.new([]) + result = Expressions.new result end .,., -module_eval(<<'.,.,', 'grammar.y', 46) +module_eval(<<'.,.,', 'grammar.y', 47) def _reduce_2(val, _values, result) - result = Expressions.new([]) + result = Expressions.new result end .,., -module_eval(<<'.,.,', 'grammar.y', 47) +module_eval(<<'.,.,', 'grammar.y', 48) def _reduce_3(val, _values, result) result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 52) +module_eval(<<'.,.,', 'grammar.y', 49) def _reduce_4(val, _values, result) - result = Expressions.new(val) + result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 53) +module_eval(<<'.,.,', 'grammar.y', 54) def _reduce_5(val, _values, result) - result = val[0] << val[2] + result = Expressions.wrap(val) result end .,., -module_eval(<<'.,.,', 'grammar.y', 54) +module_eval(<<'.,.,', 'grammar.y', 55) def _reduce_6(val, _values, result) - result = val[0] + result = val[0] << val[2] result end .,., -module_eval(<<'.,.,', 'grammar.y', 55) +module_eval(<<'.,.,', 'grammar.y', 56) def _reduce_7(val, _values, result) - result = val[1] + result = val[0] result end .,., @@ -1260,871 +1300,976 @@ def _reduce_7(val, _values, result) # reduce 24 omitted -# reduce 25 omitted +module_eval(<<'.,.,', 'grammar.y', 81) + def _reduce_25(val, _values, result) + result = val[1] + result + end +.,., -# reduce 26 omitted +module_eval(<<'.,.,', 'grammar.y', 82) + def _reduce_26(val, _values, result) + result = Expressions.new + result + end +.,., # reduce 27 omitted # reduce 28 omitted -module_eval(<<'.,.,', 'grammar.y', 101) +module_eval(<<'.,.,', 'grammar.y', 93) def _reduce_29(val, _values, result) result = LiteralNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 102) +module_eval(<<'.,.,', 'grammar.y', 94) def _reduce_30(val, _values, result) result = LiteralNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 103) +module_eval(<<'.,.,', 'grammar.y', 95) def _reduce_31(val, _values, result) result = LiteralNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 104) +module_eval(<<'.,.,', 'grammar.y', 96) def _reduce_32(val, _values, result) result = LiteralNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 105) +module_eval(<<'.,.,', 'grammar.y', 97) def _reduce_33(val, _values, result) result = LiteralNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 106) +module_eval(<<'.,.,', 'grammar.y', 98) def _reduce_34(val, _values, result) result = LiteralNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 107) +module_eval(<<'.,.,', 'grammar.y', 99) def _reduce_35(val, _values, result) result = LiteralNode.new(true) result end .,., -module_eval(<<'.,.,', 'grammar.y', 108) +module_eval(<<'.,.,', 'grammar.y', 100) def _reduce_36(val, _values, result) result = LiteralNode.new(false) result end .,., -module_eval(<<'.,.,', 'grammar.y', 109) +module_eval(<<'.,.,', 'grammar.y', 101) def _reduce_37(val, _values, result) result = LiteralNode.new(true) result end .,., -module_eval(<<'.,.,', 'grammar.y', 110) +module_eval(<<'.,.,', 'grammar.y', 102) def _reduce_38(val, _values, result) result = LiteralNode.new(false) result end .,., -module_eval(<<'.,.,', 'grammar.y', 111) +module_eval(<<'.,.,', 'grammar.y', 103) def _reduce_39(val, _values, result) result = LiteralNode.new(true) result end .,., -module_eval(<<'.,.,', 'grammar.y', 112) +module_eval(<<'.,.,', 'grammar.y', 104) def _reduce_40(val, _values, result) result = LiteralNode.new(false) result end .,., -module_eval(<<'.,.,', 'grammar.y', 117) +module_eval(<<'.,.,', 'grammar.y', 109) def _reduce_41(val, _values, result) result = AssignNode.new(val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 122) +module_eval(<<'.,.,', 'grammar.y', 114) def _reduce_42(val, _values, result) result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) result end .,., -module_eval(<<'.,.,', 'grammar.y', 123) +module_eval(<<'.,.,', 'grammar.y', 115) def _reduce_43(val, _values, result) result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) result end .,., -module_eval(<<'.,.,', 'grammar.y', 124) +module_eval(<<'.,.,', 'grammar.y', 116) def _reduce_44(val, _values, result) result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 129) +module_eval(<<'.,.,', 'grammar.y', 121) def _reduce_45(val, _values, result) result = ReturnNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 134) +module_eval(<<'.,.,', 'grammar.y', 126) def _reduce_46(val, _values, result) result = CommentNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 141) +module_eval(<<'.,.,', 'grammar.y', 133) def _reduce_47(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 142) +module_eval(<<'.,.,', 'grammar.y', 134) def _reduce_48(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 143) +module_eval(<<'.,.,', 'grammar.y', 135) def _reduce_49(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 144) +module_eval(<<'.,.,', 'grammar.y', 136) def _reduce_50(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 145) +module_eval(<<'.,.,', 'grammar.y', 137) def _reduce_51(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 146) +module_eval(<<'.,.,', 'grammar.y', 138) def _reduce_52(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 147) +module_eval(<<'.,.,', 'grammar.y', 139) def _reduce_53(val, _values, result) result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 148) +module_eval(<<'.,.,', 'grammar.y', 140) def _reduce_54(val, _values, result) - result = OpNode.new(val[1], val[0], nil, true) + result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 149) +module_eval(<<'.,.,', 'grammar.y', 141) def _reduce_55(val, _values, result) - result = OpNode.new(val[1], val[0], nil, true) + result = OpNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 151) +module_eval(<<'.,.,', 'grammar.y', 142) def _reduce_56(val, _values, result) - result = OpNode.new(val[1], val[0], val[2]) + result = OpNode.new(val[1], val[0], nil, true) result end .,., -module_eval(<<'.,.,', 'grammar.y', 152) +module_eval(<<'.,.,', 'grammar.y', 143) def _reduce_57(val, _values, result) - result = OpNode.new(val[1], val[0], val[2]) + result = OpNode.new(val[1], val[0], nil, true) result end .,., -module_eval(<<'.,.,', 'grammar.y', 153) +module_eval(<<'.,.,', 'grammar.y', 145) def _reduce_58(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 155) +module_eval(<<'.,.,', 'grammar.y', 146) def _reduce_59(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 156) +module_eval(<<'.,.,', 'grammar.y', 147) def _reduce_60(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 158) +module_eval(<<'.,.,', 'grammar.y', 149) def _reduce_61(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 159) +module_eval(<<'.,.,', 'grammar.y', 150) def _reduce_62(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 160) +module_eval(<<'.,.,', 'grammar.y', 152) def _reduce_63(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 162) +module_eval(<<'.,.,', 'grammar.y', 153) def _reduce_64(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 163) +module_eval(<<'.,.,', 'grammar.y', 154) def _reduce_65(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 164) +module_eval(<<'.,.,', 'grammar.y', 156) def _reduce_66(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 166) +module_eval(<<'.,.,', 'grammar.y', 157) def _reduce_67(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 167) +module_eval(<<'.,.,', 'grammar.y', 158) def _reduce_68(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 168) +module_eval(<<'.,.,', 'grammar.y', 160) def _reduce_69(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 169) +module_eval(<<'.,.,', 'grammar.y', 161) def _reduce_70(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 171) +module_eval(<<'.,.,', 'grammar.y', 162) def _reduce_71(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 172) +module_eval(<<'.,.,', 'grammar.y', 163) def _reduce_72(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 173) +module_eval(<<'.,.,', 'grammar.y', 165) def _reduce_73(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 174) +module_eval(<<'.,.,', 'grammar.y', 166) def _reduce_74(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 176) +module_eval(<<'.,.,', 'grammar.y', 167) def _reduce_75(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 177) +module_eval(<<'.,.,', 'grammar.y', 168) def _reduce_76(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 178) +module_eval(<<'.,.,', 'grammar.y', 170) def _reduce_77(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 179) +module_eval(<<'.,.,', 'grammar.y', 171) def _reduce_78(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 181) +module_eval(<<'.,.,', 'grammar.y', 172) def _reduce_79(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 182) +module_eval(<<'.,.,', 'grammar.y', 173) def _reduce_80(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 183) +module_eval(<<'.,.,', 'grammar.y', 175) def _reduce_81(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 184) +module_eval(<<'.,.,', 'grammar.y', 176) def _reduce_82(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 185) +module_eval(<<'.,.,', 'grammar.y', 177) def _reduce_83(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 186) +module_eval(<<'.,.,', 'grammar.y', 178) def _reduce_84(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 187) +module_eval(<<'.,.,', 'grammar.y', 179) def _reduce_85(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 189) +module_eval(<<'.,.,', 'grammar.y', 180) def _reduce_86(val, _values, result) - result = OpNode.new(val[0], val[1]) + result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 190) +module_eval(<<'.,.,', 'grammar.y', 181) def _reduce_87(val, _values, result) - result = OpNode.new(val[0], val[1]) + result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 191) +module_eval(<<'.,.,', 'grammar.y', 183) def _reduce_88(val, _values, result) result = OpNode.new(val[1], val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 196) +module_eval(<<'.,.,', 'grammar.y', 187) def _reduce_89(val, _values, result) - result = CodeNode.new(val[0], val[2]) + result = ExistenceNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 197) +module_eval(<<'.,.,', 'grammar.y', 192) def _reduce_90(val, _values, result) - result = CodeNode.new([], val[1]) + result = CodeNode.new(val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 202) +module_eval(<<'.,.,', 'grammar.y', 193) def _reduce_91(val, _values, result) - result = Expressions.new([]) + result = CodeNode.new([], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 203) +module_eval(<<'.,.,', 'grammar.y', 198) def _reduce_92(val, _values, result) - result = val[0] - result - end -.,., - -module_eval(<<'.,.,', 'grammar.y', 208) - def _reduce_93(val, _values, result) result = val result end .,., -module_eval(<<'.,.,', 'grammar.y', 209) - def _reduce_94(val, _values, result) +module_eval(<<'.,.,', 'grammar.y', 199) + def _reduce_93(val, _values, result) result = val[0] << val[2] result end .,., -module_eval(<<'.,.,', 'grammar.y', 214) +# reduce 94 omitted + +module_eval(<<'.,.,', 'grammar.y', 204) def _reduce_95(val, _values, result) - result = ValueNode.new(val[0]) + result = ParamSplatNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 215) +module_eval(<<'.,.,', 'grammar.y', 208) def _reduce_96(val, _values, result) - result = ValueNode.new(val[0]) + result = ArgSplatNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 216) +module_eval(<<'.,.,', 'grammar.y', 213) def _reduce_97(val, _values, result) result = ValueNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 217) +module_eval(<<'.,.,', 'grammar.y', 214) def _reduce_98(val, _values, result) result = ValueNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 218) +module_eval(<<'.,.,', 'grammar.y', 215) def _reduce_99(val, _values, result) result = ValueNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 219) +module_eval(<<'.,.,', 'grammar.y', 216) def _reduce_100(val, _values, result) - result = val[0] << val[1] + result = ValueNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 220) +module_eval(<<'.,.,', 'grammar.y', 217) def _reduce_101(val, _values, result) - result = ValueNode.new(val[0], [val[1]]) + result = ValueNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 225) +module_eval(<<'.,.,', 'grammar.y', 218) def _reduce_102(val, _values, result) - result = AccessorNode.new(val[1]) + result = val[0] << val[1] result end .,., -module_eval(<<'.,.,', 'grammar.y', 226) +module_eval(<<'.,.,', 'grammar.y', 219) def _reduce_103(val, _values, result) - result = val[0] + result = ValueNode.new(val[0], [val[1]]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 227) +module_eval(<<'.,.,', 'grammar.y', 224) def _reduce_104(val, _values, result) - result = SliceNode.new(val[0]) + result = AccessorNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 232) +module_eval(<<'.,.,', 'grammar.y', 225) def _reduce_105(val, _values, result) - result = IndexNode.new(val[1]) + result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 237) +module_eval(<<'.,.,', 'grammar.y', 226) def _reduce_106(val, _values, result) - result = ObjectNode.new(val[1]) + result = SliceNode.new(val[0]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 242) +module_eval(<<'.,.,', 'grammar.y', 231) def _reduce_107(val, _values, result) - result = [] + result = IndexNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 243) +module_eval(<<'.,.,', 'grammar.y', 236) def _reduce_108(val, _values, result) - result = val + result = ObjectNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 244) +module_eval(<<'.,.,', 'grammar.y', 241) def _reduce_109(val, _values, result) - result = val[0] << val[2] + result = [] result end .,., -module_eval(<<'.,.,', 'grammar.y', 245) +module_eval(<<'.,.,', 'grammar.y', 242) def _reduce_110(val, _values, result) - result = val[0] << val[2] + result = val result end .,., -module_eval(<<'.,.,', 'grammar.y', 250) +module_eval(<<'.,.,', 'grammar.y', 243) def _reduce_111(val, _values, result) - result = val[0] + result = val[0] << val[2] result end .,., -module_eval(<<'.,.,', 'grammar.y', 251) +module_eval(<<'.,.,', 'grammar.y', 244) def _reduce_112(val, _values, result) - result = val[1].new_instance + result = val[0] << val[2] result end .,., -module_eval(<<'.,.,', 'grammar.y', 252) +module_eval(<<'.,.,', 'grammar.y', 246) def _reduce_113(val, _values, result) - result = val[0] + result = val[0] << val[3] result end .,., -module_eval(<<'.,.,', 'grammar.y', 257) +module_eval(<<'.,.,', 'grammar.y', 247) def _reduce_114(val, _values, result) - result = ExtendsNode.new(val[0], val[2]) + result = val[1] result end .,., -module_eval(<<'.,.,', 'grammar.y', 262) +module_eval(<<'.,.,', 'grammar.y', 252) def _reduce_115(val, _values, result) - result = CallNode.new(val[0], val[2]) + result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 263) +module_eval(<<'.,.,', 'grammar.y', 253) def _reduce_116(val, _values, result) - result = CallNode.new(val[0], val[2]) + result = val[1].new_instance result end .,., -module_eval(<<'.,.,', 'grammar.y', 268) +module_eval(<<'.,.,', 'grammar.y', 254) def _reduce_117(val, _values, result) - result = CallNode.new(:super, val[2]) + result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 273) +module_eval(<<'.,.,', 'grammar.y', 259) def _reduce_118(val, _values, result) - result = RangeNode.new(val[1], val[4]) + result = ExtendsNode.new(val[0], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 274) +module_eval(<<'.,.,', 'grammar.y', 264) def _reduce_119(val, _values, result) - result = RangeNode.new(val[1], val[5], true) + result = CallNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 279) +module_eval(<<'.,.,', 'grammar.y', 265) def _reduce_120(val, _values, result) - result = ArrayNode.new(val[1]) + result = CallNode.new(val[0], val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 284) +module_eval(<<'.,.,', 'grammar.y', 270) def _reduce_121(val, _values, result) - result = [] + result = val[1] result end .,., -module_eval(<<'.,.,', 'grammar.y', 285) +module_eval(<<'.,.,', 'grammar.y', 271) def _reduce_122(val, _values, result) - result = val + result = val[1] << val[3] result end .,., -module_eval(<<'.,.,', 'grammar.y', 286) +module_eval(<<'.,.,', 'grammar.y', 276) def _reduce_123(val, _values, result) - result = val[0] << val[2] + result = CallNode.new(:super, val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 287) +module_eval(<<'.,.,', 'grammar.y', 282) def _reduce_124(val, _values, result) - result = val[0] << val[2] + result = RangeNode.new(val[1], val[4]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 292) +module_eval(<<'.,.,', 'grammar.y', 284) def _reduce_125(val, _values, result) - result = TryNode.new(val[1], val[2][0], val[2][1]) + result = RangeNode.new(val[1], val[5], true) result end .,., -module_eval(<<'.,.,', 'grammar.y', 294) +module_eval(<<'.,.,', 'grammar.y', 289) def _reduce_126(val, _values, result) - result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) + result = ArrayNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 299) +module_eval(<<'.,.,', 'grammar.y', 294) def _reduce_127(val, _values, result) - result = [nil, nil] + result = [] result end .,., -module_eval(<<'.,.,', 'grammar.y', 300) +module_eval(<<'.,.,', 'grammar.y', 295) def _reduce_128(val, _values, result) - result = [val[1], val[2]] + result = val result end .,., -module_eval(<<'.,.,', 'grammar.y', 305) +module_eval(<<'.,.,', 'grammar.y', 296) def _reduce_129(val, _values, result) - result = ThrowNode.new(val[1]) + result = [val[1]] result end .,., -module_eval(<<'.,.,', 'grammar.y', 310) +module_eval(<<'.,.,', 'grammar.y', 297) def _reduce_130(val, _values, result) - result = ParentheticalNode.new(val[1]) + result = val[0] << val[2] result end .,., -module_eval(<<'.,.,', 'grammar.y', 316) +module_eval(<<'.,.,', 'grammar.y', 298) def _reduce_131(val, _values, result) - result = WhileNode.new(val[1], val[3]) + result = val[0] << val[2] result end .,., -module_eval(<<'.,.,', 'grammar.y', 323) +module_eval(<<'.,.,', 'grammar.y', 299) def _reduce_132(val, _values, result) - result = ForNode.new(val[0], val[3][0], val[2][0], val[3][1], val[2][1]) + result = val[0] << val[3] result end .,., -module_eval(<<'.,.,', 'grammar.y', 328) +module_eval(<<'.,.,', 'grammar.y', 300) def _reduce_133(val, _values, result) - result = val + result = val[0] << val[3] result end .,., -module_eval(<<'.,.,', 'grammar.y', 329) +module_eval(<<'.,.,', 'grammar.y', 301) def _reduce_134(val, _values, result) - result = [val[0], val[2]] + result = val[0] result end .,., -module_eval(<<'.,.,', 'grammar.y', 334) +module_eval(<<'.,.,', 'grammar.y', 306) def _reduce_135(val, _values, result) - result = [val[1]] + result = TryNode.new(val[1], val[2][0], val[2][1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 336) +module_eval(<<'.,.,', 'grammar.y', 307) def _reduce_136(val, _values, result) - result = [val[1], val[3]] + result = TryNode.new(val[1], nil, nil, val[3]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 342) +module_eval(<<'.,.,', 'grammar.y', 309) def _reduce_137(val, _values, result) - result = val[3].rewrite_condition(val[1]) + result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 344) +module_eval(<<'.,.,', 'grammar.y', 314) def _reduce_138(val, _values, result) - result = val[3].rewrite_condition(val[1]).add_else(val[5]) + result = [val[1], val[2]] result end .,., -module_eval(<<'.,.,', 'grammar.y', 349) +module_eval(<<'.,.,', 'grammar.y', 319) def _reduce_139(val, _values, result) - result = val[0] + result = ThrowNode.new(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 350) +module_eval(<<'.,.,', 'grammar.y', 324) def _reduce_140(val, _values, result) - result = val[0] << val[1] + result = ParentheticalNode.new(val[1], val[0].line) result end .,., -module_eval(<<'.,.,', 'grammar.y', 355) +module_eval(<<'.,.,', 'grammar.y', 329) def _reduce_141(val, _values, result) - result = IfNode.new(val[1], val[3]) + result = WhileNode.new(val[1], val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 364) +module_eval(<<'.,.,', 'grammar.y', 336) def _reduce_142(val, _values, result) - result = IfNode.new(val[2], val[4]) + result = ForNode.new(val[0], val[3], val[2][0], val[2][1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 369) +module_eval(<<'.,.,', 'grammar.y', 337) def _reduce_143(val, _values, result) - result = val[0] + result = ForNode.new(val[3], val[2], val[1][0], val[1][1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 370) +module_eval(<<'.,.,', 'grammar.y', 342) def _reduce_144(val, _values, result) - result = val[0].add_else(val[1]) + result = val result end .,., -module_eval(<<'.,.,', 'grammar.y', 375) +module_eval(<<'.,.,', 'grammar.y', 343) def _reduce_145(val, _values, result) - result = nil + result = [val[0], val[2]] result end .,., -module_eval(<<'.,.,', 'grammar.y', 376) +module_eval(<<'.,.,', 'grammar.y', 348) def _reduce_146(val, _values, result) - result = val[1] + result = {:source => val[1]} result end .,., -module_eval(<<'.,.,', 'grammar.y', 381) +module_eval(<<'.,.,', 'grammar.y', 350) def _reduce_147(val, _values, result) - result = val[0] + result = val[0].merge(:filter => val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 382) +module_eval(<<'.,.,', 'grammar.y', 352) def _reduce_148(val, _values, result) - result = val[0].add_else(val[1]) + result = val[0].merge(:step => val[2]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 388) +module_eval(<<'.,.,', 'grammar.y', 358) def _reduce_149(val, _values, result) - result = IfNode.new(val[1], val[3], val[4]) + result = val[3].rewrite_condition(val[1]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 389) +module_eval(<<'.,.,', 'grammar.y', 360) def _reduce_150(val, _values, result) - result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true}) + result = val[3].rewrite_condition(val[1]).add_else(val[5]) result end .,., -module_eval(<<'.,.,', 'grammar.y', 390) +module_eval(<<'.,.,', 'grammar.y', 365) def _reduce_151(val, _values, result) - result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true, :invert => true}) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 366) + def _reduce_152(val, _values, result) + result = val[0] << val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 371) + def _reduce_153(val, _values, result) + result = IfNode.new(val[1], val[2], nil, {:statement => true}) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 373) + def _reduce_154(val, _values, result) + result = IfNode.new(val[1], val[2], nil, {:statement => true}) + result + end +.,., + +# reduce 155 omitted + +module_eval(<<'.,.,', 'grammar.y', 381) + def _reduce_156(val, _values, result) + result = IfNode.new(val[1], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 386) + def _reduce_157(val, _values, result) + result = val[1].force_statement + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 391) + def _reduce_158(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 392) + def _reduce_159(val, _values, result) + result = val[0].add_else(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 397) + def _reduce_160(val, _values, result) + result = nil + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 398) + def _reduce_161(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 403) + def _reduce_162(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 404) + def _reduce_163(val, _values, result) + result = val[0].add_else(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 409) + def _reduce_164(val, _values, result) + result = val[0].add_else(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 410) + def _reduce_165(val, _values, result) + result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true}) + result + end +.,., + +module_eval(<<'.,.,', 'grammar.y', 411) + def _reduce_166(val, _values, result) + result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true, :invert => true}) result end .,., diff --git a/lib/coffee_script/rewriter.rb b/lib/coffee_script/rewriter.rb new file mode 100644 index 0000000000..88a31066d5 --- /dev/null +++ b/lib/coffee_script/rewriter.rb @@ -0,0 +1,208 @@ +module CoffeeScript + + # In order to keep the grammar simple, the stream of tokens that the Lexer + # emits is rewritten by the Rewriter, smoothing out ambiguities, mis-nested + # indentation, and single-line flavors of expressions. + class Rewriter + + # Tokens that must be balanced. + BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], [:INDENT, :OUTDENT]] + + # Tokens that signal the start of a balanced pair. + EXPRESSION_START = BALANCED_PAIRS.map {|pair| pair.first } + + # Tokens that signal the end of a balanced pair. + EXPRESSION_TAIL = BALANCED_PAIRS.map {|pair| pair.last } + + # Tokens that indicate the close of a clause of an expression. + EXPRESSION_CLOSE = [:CATCH, :WHEN, :ELSE, :FINALLY] + EXPRESSION_TAIL + + # The inverse mappings of token pairs we're trying to fix up. + INVERSES = BALANCED_PAIRS.inject({}) do |memo, pair| + memo[pair.first] = pair.last + memo[pair.last] = pair.first + memo + end + + # 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] + + # Rewrite the token stream in multiple passes, one logical filter at + # a time. This could certainly be changed into a single pass through the + # stream, with a big ol' efficient switch, but it's much nicer like this. + def rewrite(tokens) + @tokens = tokens + adjust_comments + remove_mid_expression_newlines + move_commas_outside_outdents + add_implicit_indentation + ensure_balance(*BALANCED_PAIRS) + rewrite_closing_parens + @tokens + end + + # Rewrite the token stream, looking one token ahead and behind. + # Allow the return value of the block to tell us how many tokens to move + # forwards (or backwards) in the stream, to make sure we don't miss anything + # as the stream changes length under our feet. + def scan_tokens + i = 0 + loop do + break unless @tokens[i] + move = yield(@tokens[i - 1], @tokens[i], @tokens[i + 1], i) + i += move + end + end + + # Massage newlines and indentations so that comments don't have to be + # correctly indented, or appear on their own line. + def adjust_comments + scan_tokens do |prev, token, post, i| + next 1 unless token[0] == :COMMENT + before, after = @tokens[i - 2], @tokens[i + 2] + if before && after && + ((before[0] == :INDENT && after[0] == :OUTDENT) || + (before[0] == :OUTDENT && after[0] == :INDENT)) && + before[1] == after[1] + @tokens.delete_at(i + 2) + @tokens.delete_at(i - 2) + next 0 + elsif !["\n", :INDENT, :OUTDENT].include?(prev[0]) + @tokens.insert(i, ["\n", Value.new("\n", token[1].line)]) + next 2 + else + next 1 + end + end + end + + # Some blocks occur in the middle of expressions -- when we're expecting + # this, remove their trailing newlines. + def remove_mid_expression_newlines + scan_tokens do |prev, token, post, i| + next 1 unless post && EXPRESSION_CLOSE.include?(post[0]) && token[0] == "\n" + @tokens.delete_at(i) + next 0 + end + end + + # Make sure that we don't accidentally break trailing commas, which need + # to go on the outside of expression closers. + def move_commas_outside_outdents + scan_tokens do |prev, token, post, i| + if token[0] == :OUTDENT && prev[0] == ',' + @tokens.delete_at(i) + @tokens.insert(i - 1, token) + 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. + # ')' can close a single-line block, but we need to make sure it's balanced. + 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. + line = token[1].line + @tokens.insert(i + 1, [:INDENT, Value.new(2, line)]) + idx = i + 1 + parens = 0 + 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)]) + break + end + parens += 1 if tok[0] == '(' + parens -= 1 if tok[0] == ')' + end + next 1 unless token[0] == :THEN + @tokens.delete_at(i) + next 0 + 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) + 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 + 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 + end + + # We'd like to support syntax like this: + # el.click(event => + # el.hide()) + # In order to accomplish this, move outdents that follow closing parens + # inwards, safely. The steps to accomplish this are: + # + # 1. Check that all paired tokens are balanced and in order. + # 2. Rewrite the stream with a stack: if you see an '(' or INDENT, add it + # to the stack. If you see an ')' or OUTDENT, pop the stack and replace + # it with the inverse of what we've just popped. + # 3. Keep track of "debt" for tokens that we fake, to make sure we end + # up balanced in the end. + # + def rewrite_closing_parens + verbose = ENV['VERBOSE'] + stack, debt = [], Hash.new(0) + stack_stats = lambda { "stack: #{stack.inspect} debt: #{debt.inspect}\n\n" } + puts "rewrite_closing_original: #{@tokens.inspect}" if verbose + scan_tokens do |prev, token, post, i| + tag, inv = token[0], INVERSES[token[0]] + # Push openers onto the stack. + if EXPRESSION_START.include?(tag) + stack.push(token) + puts "pushing #{tag} #{stack_stats[]}" if verbose + next 1 + # The end of an expression, check stack and debt for a pair. + elsif EXPRESSION_TAIL.include?(tag) + puts @tokens[i..-1].inspect if verbose + # If the tag is already in our debt, swallow it. + if debt[inv] > 0 + debt[inv] -= 1 + @tokens.delete_at(i) + puts "tag in debt #{tag} #{stack_stats[]}" if verbose + next 0 + else + # Pop the stack of open delimiters. + match = stack.pop + mtag = match[0] + # Continue onwards if it's the expected tag. + if tag == INVERSES[mtag] + puts "expected tag #{tag} #{stack_stats[]}" if verbose + next 1 + else + # Unexpected close, insert correct close, adding to the debt. + debt[mtag] += 1 + puts "unexpected #{tag}, replacing with #{INVERSES[mtag]} #{stack_stats[]}" if verbose + val = mtag == :INDENT ? match[1] : INVERSES[mtag] + @tokens.insert(i, [INVERSES[mtag], Value.new(val, token[1].line)]) + next 1 + end + end + else + # Uninteresting token: + next 1 + end + end + end + + end +end \ No newline at end of file diff --git a/lib/coffee_script/scope.rb b/lib/coffee_script/scope.rb index 5e510b12ca..4cb61b0de8 100644 --- a/lib/coffee_script/scope.rb +++ b/lib/coffee_script/scope.rb @@ -5,18 +5,19 @@ module CoffeeScript # whether a variable has been seen before or if it needs to be declared. class Scope - attr_reader :parent, :variables, :temp_variable + attr_reader :parent, :expressions, :variables, :temp_variable - # Initialize a scope with its parent, for lookups up the chain. - def initialize(parent=nil) - @parent = parent + # Initialize a scope with its parent, for lookups up the chain, + # as well as the Expressions body where it should declare its variables. + def initialize(parent, expressions) + @parent, @expressions = parent, expressions @variables = {} - @temp_variable = @parent ? @parent.temp_variable : '__a' + @temp_variable = @parent ? @parent.temp_variable.dup : '__a' end # Look up a variable in lexical scope, or declare it if not found. def find(name, remote=false) - found = check(name, remote) + found = check(name) return found if found || remote @variables[name.to_sym] = :var found @@ -29,9 +30,9 @@ def parameter(name) end # Just check to see if a variable has already been declared. - def check(name, remote=false) + def check(name) return true if @variables[name.to_sym] - @parent && @parent.find(name, true) + !!(@parent && @parent.check(name)) end # You can reset a found variable on the immediate scope. @@ -46,8 +47,8 @@ def free_variable @temp_variable.dup end - def any_declared? - !declared_variables.empty? + def declarations?(body) + !declared_variables.empty? && body == @expressions end # Return the list of variables first declared in current scope. @@ -55,6 +56,10 @@ def declared_variables @variables.select {|k, v| v == :var }.map {|pair| pair[0].to_s }.sort end + def inspect + "" + end + end end \ No newline at end of file diff --git a/package.json b/package.json index 7d83b675e0..bb842ff87a 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "coffee-script", - "lib": "lib/coffee_script/narwhal/js", - "preload": ["loader"], + "lib": "lib/coffee_script/narwhal/lib", + "preload": ["coffee-script/loader"], "description": "Unfancy JavaScript", "keywords": ["javascript", "language"], "author": "Jeremy Ashkenas", - "version": "0.1.6" + "version": "0.2.0" } diff --git a/test/fixtures/execution/test_arguments.coffee b/test/fixtures/execution/test_arguments.coffee new file mode 100644 index 0000000000..21fdbcac30 --- /dev/null +++ b/test/fixtures/execution/test_arguments.coffee @@ -0,0 +1,17 @@ +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) diff --git a/test/fixtures/execution/test_array_comprehension.coffee b/test/fixtures/execution/test_array_comprehension.coffee index 973a595a67..27d0487118 100644 --- a/test/fixtures/execution/test_array_comprehension.coffee +++ b/test/fixtures/execution/test_array_comprehension.coffee @@ -1,4 +1,21 @@ -nums: n * n for n in [1, 2, 3] if n % 2 isnt 0. -result: n * 2 for n in nums. +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') + + +obj: {one: 1, two: 2, three: 3} +names: key + '!' for value, key in obj +odds: key + '!' for value, key in obj when value % 2 isnt 0 + +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 + num *= -1 + num -= 2 + num * -1 + +print(evens.join(', ') is '4, 6, 8') -print(result.join(',') is '2,18') \ No newline at end of file diff --git a/test/fixtures/execution/test_assign_to_try_catch.coffee b/test/fixtures/execution/test_assign_to_try_catch.coffee index a8397fd05d..9de8178f02 100644 --- a/test/fixtures/execution/test_assign_to_try_catch.coffee +++ b/test/fixtures/execution/test_assign_to_try_catch.coffee @@ -1,6 +1,8 @@ result: try nonexistent * missing catch error - true. - -print(result) \ No newline at end of file + true + +result2: try nonexistent * missing catch error then true + +print(result is true and result2 is true) \ No newline at end of file diff --git a/test/fixtures/execution/test_blocks.coffee b/test/fixtures/execution/test_blocks.coffee new file mode 100644 index 0000000000..a28eecc955 --- /dev/null +++ b/test/fixtures/execution/test_blocks.coffee @@ -0,0 +1,4 @@ +results: [1, 2, 3].map() x => + x * x + +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 10e52c49ef..8a9d4bc1ff 100644 --- a/test/fixtures/execution/test_calling_super.coffee +++ b/test/fixtures/execution/test_calling_super.coffee @@ -1,21 +1,21 @@ -Base: => . +Base: => Base.prototype.func: string => - 'zero/' + string. + 'zero/' + string -FirstChild: => . +FirstChild: => FirstChild extends Base FirstChild.prototype.func: string => - super('one/') + string. - -SecondChild: => . + super('one/') + string + +SecondChild: => SecondChild extends FirstChild SecondChild.prototype.func: string => - super('two/') + string. - -ThirdChild: => . + super('two/') + string + +ThirdChild: => ThirdChild extends SecondChild ThirdChild.prototype.func: string => - super('three/') + string. + super('three/') + string result: (new ThirdChild()).func('four') diff --git a/test/fixtures/execution/test_chained_calls.coffee b/test/fixtures/execution/test_chained_calls.coffee index ac0ef26914..4cf76ec3a9 100644 --- a/test/fixtures/execution/test_chained_calls.coffee +++ b/test/fixtures/execution/test_chained_calls.coffee @@ -1,4 +1,4 @@ -identity_wrap: x => => x.. +identity_wrap: x => => x result: identity_wrap(identity_wrap(true))()() diff --git a/test/fixtures/execution/test_everything.coffee b/test/fixtures/execution/test_everything.coffee index ca24c6400a..87d444925c 100644 --- a/test/fixtures/execution/test_everything.coffee +++ b/test/fixtures/execution/test_everything.coffee @@ -1,12 +1,15 @@ func: => a: 3 b: [] + while a >= 0 b.push('o') - a--. + a-- c: { "text": b + other: null + something_else: x => x + 5 } c: 'error' unless 42 > 41 @@ -14,14 +17,13 @@ func: => c.text: if false 'error' else - c.text + '---'. - + c.text + '---' d = { text = c.text } - c.list: l for l in d.text.split('') if l is '-'. + c.list: l for l in d.text.split('') when l is '-' - c.single: c.list[1..1][0]. + c.single: c.list[1..1][0] print(func() == '-') diff --git a/test/fixtures/execution/test_existence.coffee b/test/fixtures/execution/test_existence.coffee new file mode 100644 index 0000000000..47bfbfab65 --- /dev/null +++ b/test/fixtures/execution/test_existence.coffee @@ -0,0 +1,5 @@ +print(if my_special_variable? then false else true) + +my_special_variable: false + +print(if my_special_variable? then true else false) \ 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 9e14947bf6..1e7546a0a1 100644 --- a/test/fixtures/execution/test_fancy_if_statement.coffee +++ b/test/fixtures/execution/test_fancy_if_statement.coffee @@ -3,9 +3,8 @@ c: false result: if a if b - if c then false - else + if c then false else if d - true.... + true print(result) \ No newline at end of file diff --git a/test/fixtures/execution/test_funky_comments.coffee b/test/fixtures/execution/test_funky_comments.coffee new file mode 100644 index 0000000000..2a24318d40 --- /dev/null +++ b/test/fixtures/execution/test_funky_comments.coffee @@ -0,0 +1,8 @@ +func: => + false + false # comment + false +# comment + true + +print(func()) \ No newline at end of file diff --git a/test/fixtures/execution/test_literals.coffee b/test/fixtures/execution/test_literals.coffee new file mode 100644 index 0000000000..27fec2d36e --- /dev/null +++ b/test/fixtures/execution/test_literals.coffee @@ -0,0 +1,14 @@ +a: [(x => x), (x => x * x)] + +print(a.length is 2) + + +regex: /match/i +words: "I think there is a match in here." + +print(!!words.match(regex)) + + +neg: (3 -4) + +print(neg is -1) \ No newline at end of file diff --git a/test/fixtures/execution/test_named_functions.coffee b/test/fixtures/execution/test_named_functions.coffee new file mode 100644 index 0000000000..4fb9998b49 --- /dev/null +++ b/test/fixtures/execution/test_named_functions.coffee @@ -0,0 +1,8 @@ +x: 1 +y: {} +y.x: => 3 + +print(x is 1) +print(typeof(y.x) is 'function') +print(y.x() is 3) +print(y.x.name is 'x') \ No newline at end of file diff --git a/test/fixtures/execution/test_nested_comprehensions.coffee b/test/fixtures/execution/test_nested_comprehensions.coffee new file mode 100644 index 0000000000..ce6952d857 --- /dev/null +++ b/test/fixtures/execution/test_nested_comprehensions.coffee @@ -0,0 +1,11 @@ +multi_liner: + for x in [3..5] + for y in [3..5] + [x, y] + +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]) diff --git a/test/fixtures/execution/test_newline_escaping.coffee b/test/fixtures/execution/test_newline_escaping.coffee index 2f52e9327a..117c228479 100644 --- a/test/fixtures/execution/test_newline_escaping.coffee +++ b/test/fixtures/execution/test_newline_escaping.coffee @@ -1,6 +1,6 @@ -six: \ - 1 + \ - 2 + \ - 3 +six: + 1 + + 2 + + 3 print(six is 6) \ No newline at end of file diff --git a/test/fixtures/execution/test_range_comprehension.coffee b/test/fixtures/execution/test_range_comprehension.coffee index 8ae0b3d803..8917550b41 100644 --- a/test/fixtures/execution/test_range_comprehension.coffee +++ b/test/fixtures/execution/test_range_comprehension.coffee @@ -1,8 +1,20 @@ -nums: i * 3 for i in [1..3]. +nums: i * 3 for i in [1..3] -negs: x for x in [-20..-10]. +negs: x for x in [-20..-5*2] negs: negs[0..2] result: nums.concat(negs).join(', ') -print(result is '3, 6, 9, -20, -19, -18') \ No newline at end of file +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') + +# 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 diff --git a/test/fixtures/execution/test_splats.coffee b/test/fixtures/execution/test_splats.coffee new file mode 100644 index 0000000000..c5881bbe79 --- /dev/null +++ b/test/fixtures/execution/test_splats.coffee @@ -0,0 +1,35 @@ +func: first, second, *rest => + rest.join(' ') + +result: func(1, 2, 3, 4, 5) + +print(result is "3 4 5") + + +gold: silver: bronze: the_field: null + +medalists: first, second, third, *rest => + gold: first + silver: second + bronze: third + 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("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 diff --git a/test/fixtures/execution/test_splices.coffee b/test/fixtures/execution/test_splices.coffee new file mode 100644 index 0000000000..0ac1135f99 --- /dev/null +++ b/test/fixtures/execution/test_splices.coffee @@ -0,0 +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 diff --git a/test/fixtures/execution/test_switch.coffee b/test/fixtures/execution/test_switch.coffee index bce30883cd..dad4335896 100644 --- a/test/fixtures/execution/test_switch.coffee +++ b/test/fixtures/execution/test_switch.coffee @@ -1,11 +1,13 @@ num: 10 result: switch num -when 5 then false -when 'a' - false -when 10 then true -when 11 then false -else false. - + when 5 then false + when 'a' + true + true + false + when 10 then true + when 11 then false + else false + print(result) diff --git a/test/fixtures/generation/each.coffee b/test/fixtures/generation/each.coffee index f783302fe3..89bade6171 100644 --- a/test/fixtures/generation/each.coffee +++ b/test/fixtures/generation/each.coffee @@ -6,9 +6,9 @@ _.each: obj, iterator, context => if obj.forEach obj.forEach(iterator, context) else if _.isArray(obj) or _.isArguments(obj) - iterator.call(context, item, i, obj) for item, i in obj. + iterator.call(context, item, i, obj) for item, i in obj else - iterator.call(context, obj[key], key, obj) for key in _.keys(obj).. + iterator.call(context, obj[key], key, obj) for key in _.keys(obj) catch e - throw e if e isnt breaker. - obj. \ No newline at end of file + throw e if e isnt breaker + obj \ No newline at end of file diff --git a/test/fixtures/generation/each.js b/test/fixtures/generation/each.js index 8787ea0642..3dfdaa3f77 100644 --- a/test/fixtures/generation/each.js +++ b/test/fixtures/generation/each.js @@ -2,29 +2,28 @@ // The cornerstone, an each implementation. // Handles objects implementing forEach, arrays, and raw objects. - _.each = function(obj, iterator, context) { - var __a, __b, __c, __d, __e, __f, __g, __h, i, index, item, key; + _.each = function each(obj, iterator, context) { + var __a, __b, __c, __d, __e, i, index, item, key; index = 0; try { if (obj.forEach) { obj.forEach(iterator, context); } else if (_.isArray(obj) || _.isArguments(obj)) { __a = obj; - __d = []; - for (__b=0, __c=__a.length; __b<__c; __b++) { - item = __a[__b]; - i = __b; - __d[__b] = iterator.call(context, item, i, obj); + for (i in __a) { + if (__a.hasOwnProperty(i)) { + item = __a[i]; + iterator.call(context, item, i, obj); + } } - __d; } else { - __e = _.keys(obj); - __h = []; - for (__f=0, __g=__e.length; __f<__g; __f++) { - key = __e[__f]; - __h[__f] = iterator.call(context, obj[key], key, obj); + __c = _.keys(obj); + for (__d in __c) { + if (__c.hasOwnProperty(__d)) { + key = __c[__d]; + iterator.call(context, obj[key], key, obj); + } } - __h; } } catch (e) { if (e !== breaker) { diff --git a/test/fixtures/generation/each.tokens b/test/fixtures/generation/each.tokens index 149a3170c7..aa5d853e2a 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"], ["=>", "=>"], ["\n", "\n"], [:IDENTIFIER, "index"], [:ASSIGN, ":"], [:NUMBER, "0"], ["\n", "\n"], [:TRY, "try"], ["\n", "\n"], [:IF, "if"], [:IDENTIFIER, "obj"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "forEach"], ["\n", "\n"], [:IDENTIFIER, "obj"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "forEach"], ["(", "("], [:IDENTIFIER, "iterator"], [",", ","], [:IDENTIFIER, "context"], [")", ")"], ["\n", "\n"], [:ELSE, "else"], [:IF, "if"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "isArray"], ["(", "("], [:IDENTIFIER, "obj"], [")", ")"], [:OR, "or"], [:IDENTIFIER, "_"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "isArguments"], ["(", "("], [:IDENTIFIER, "obj"], [")", ")"], ["\n", "\n"], [:IDENTIFIER, "iterator"], [:PROPERTY_ACCESS, "."], [:IDENTIFIER, "call"], ["(", "("], [:IDENTIFIER, "context"], [",", ","], [:IDENTIFIER, "item"], [",", ","], [:IDENTIFIER, "i"], [",", ","], [:IDENTIFIER, "obj"], [")", ")"], [:FOR, "for"], [:IDENTIFIER, "item"], [",", ","], [:IDENTIFIER, "i"], [:IN, "in"], [:IDENTIFIER, "obj"], [".", "."], ["\n", "\n"], [:ELSE, "else"], ["\n", "\n"], [: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"], [")", ")"], [".", "."], [".", "."], ["\n", "\n"], [:CATCH, "catch"], [:IDENTIFIER, "e"], ["\n", "\n"], [:THROW, "throw"], [:IDENTIFIER, "e"], [:IF, "if"], [:IDENTIFIER, "e"], [:ISNT, "isnt"], [:IDENTIFIER, "breaker"], [".", "."], ["\n", "\n"], [:IDENTIFIER, "obj"], [".", "."]] \ 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, "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 diff --git a/test/fixtures/generation/each_no_wrap.js b/test/fixtures/generation/each_no_wrap.js index aa88e142c2..40ee9e4cc8 100644 --- a/test/fixtures/generation/each_no_wrap.js +++ b/test/fixtures/generation/each_no_wrap.js @@ -1,29 +1,28 @@ // The cornerstone, an each implementation. // Handles objects implementing forEach, arrays, and raw objects. -_.each = function(obj, iterator, context) { - var __a, __b, __c, __d, __e, __f, __g, __h, i, index, item, key; +_.each = function each(obj, iterator, context) { + var __a, __b, __c, __d, __e, i, index, item, key; index = 0; try { if (obj.forEach) { obj.forEach(iterator, context); } else if (_.isArray(obj) || _.isArguments(obj)) { __a = obj; - __d = []; - for (__b=0, __c=__a.length; __b<__c; __b++) { - item = __a[__b]; - i = __b; - __d[__b] = iterator.call(context, item, i, obj); + for (i in __a) { + if (__a.hasOwnProperty(i)) { + item = __a[i]; + iterator.call(context, item, i, obj); + } } - __d; } else { - __e = _.keys(obj); - __h = []; - for (__f=0, __g=__e.length; __f<__g; __f++) { - key = __e[__f]; - __h[__f] = iterator.call(context, obj[key], key, obj); + __c = _.keys(obj); + for (__d in __c) { + if (__c.hasOwnProperty(__d)) { + key = __c[__d]; + iterator.call(context, obj[key], key, obj); + } } - __h; } } catch (e) { if (e !== breaker) { diff --git a/test/fixtures/generation/statements_as_expressions.coffee b/test/fixtures/generation/statements_as_expressions.coffee new file mode 100644 index 0000000000..0541d95fe2 --- /dev/null +++ b/test/fixtures/generation/statements_as_expressions.coffee @@ -0,0 +1,16 @@ +# Everything should be able to be an expression. + +result: while sunny? + go_outside() + +print(3 + try + nonexistent.no_way +catch error + print(error) + 3 +) + +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 new file mode 100644 index 0000000000..450fd9e5b0 --- /dev/null +++ b/test/fixtures/generation/whitespace.coffee @@ -0,0 +1,20 @@ +# test +f1: x => + x * x + f2: y => + y * x + f3: 3 + +# Parens can close on the proper level. +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 => + 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 0737fdd3ae..1a72f9943c 100644 --- a/test/unit/test_execution.rb +++ b/test/unit/test_execution.rb @@ -2,27 +2,35 @@ class ExecutionTest < Test::Unit::TestCase - NO_WARNINGS = /\A(0 error\(s\), 0 warning\(s\)\n)+\Z/ - ALLS_WELL = /\A\n?(true\n)+\Z/m + NO_WARNINGS = "0 error(s), 0 warning(s)" + # This is by far the most important test. It evaluates all of the + # CoffeeScript in test/fixtures/execution, ensuring that all our + # syntax actually works. def test_execution_of_coffeescript sources = ['test/fixtures/execution/*.coffee'].join(' ') - assert `bin/coffee -r #{sources}`.match(ALLS_WELL) + (`bin/coffee -r #{sources}`).split("\n").each do |line| + assert line == "true" + end end - def test_lintless_coffeescript - lint_results = `bin/coffee -l test/fixtures/execution/*.coffee` - assert lint_results.match(NO_WARNINGS) + def test_lintless_tests + no_warnings `bin/coffee -l test/fixtures/*/*.coffee` end def test_lintless_examples - lint_results = `bin/coffee -l examples/*.coffee` - assert lint_results.match(NO_WARNINGS) + no_warnings `bin/coffee -l examples/*.coffee` end def test_lintless_documentation - lint_results = `bin/coffee -l documentation/coffee/*.coffee` - assert lint_results.match(NO_WARNINGS) + no_warnings `bin/coffee -l documentation/coffee/*.coffee` + end + + + private + + def no_warnings(output) + output.split("\n").each {|line| assert line == NO_WARNINGS } end end diff --git a/test/unit/test_lexer.rb b/test/unit/test_lexer.rb index 0d2ec1b598..5a811d3435 100644 --- a/test/unit/test_lexer.rb +++ b/test/unit/test_lexer.rb @@ -7,45 +7,47 @@ def setup end def test_lexing_an_empty_string - assert @lex.tokenize("") == [] + assert @lex.tokenize("") == [["\n", "\n"]] end def test_lexing_basic_assignment - code = "a: 'one'; b: [1, 2]" - assert @lex.tokenize(code) == [[:IDENTIFIER, "a"], [:ASSIGN, ":"], - [:STRING, "'one'"], [";", ";"], [:IDENTIFIER, "b"], [:ASSIGN, ":"], - ["[", "["], [:NUMBER, "1"], [",", ","], [:NUMBER, "2"], ["]", "]"]] + code = "a: 'one'\nb: [1, 2]" + assert @lex.tokenize(code) == [[:IDENTIFIER, "a"], [:ASSIGN, ":"], + [:STRING, "'one'"], ["\n", "\n"], [:IDENTIFIER, "b"], [:ASSIGN, ":"], + ["[", "["], [:NUMBER, "1"], [",", ","], [:NUMBER, "2"], ["]", "]"], + ["\n", "\n"]] end def test_lexing_object_literal code = "{one : 1}" assert @lex.tokenize(code) == [["{", "{"], [:IDENTIFIER, "one"], [:ASSIGN, ":"], - [:NUMBER, "1"], ["}", "}"]] + [:NUMBER, "1"], ["}", "}"], ["\n", "\n"]] end def test_lexing_function_definition - code = "x, y => x * y." + code = "x, y => x * y" assert @lex.tokenize(code) == [[:PARAM, "x"], [",", ","], [:PARAM, "y"], - ["=>", "=>"], [:IDENTIFIER, "x"], ["*", "*"], [:IDENTIFIER, "y"], [".", "."]] + ["=>", "=>"], [: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"]] + [")", ")"], [:IF, "if"], [:IDENTIFIER, "happy"], ["\n", "\n"]] end def test_lexing_comment - code = "a: 1\n # comment\n # on two lines\nb: 2" + code = "a: 1\n# comment\n# on two lines\nb: 2" assert @lex.tokenize(code) == [[:IDENTIFIER, "a"], [:ASSIGN, ":"], [:NUMBER, "1"], ["\n", "\n"], [:COMMENT, [" comment", " on two lines"]], ["\n", "\n"], - [:IDENTIFIER, "b"], [:ASSIGN, ":"], [:NUMBER, "2"]] + [:IDENTIFIER, "b"], [:ASSIGN, ":"], [:NUMBER, "2"], ["\n", "\n"]] end def test_lexing_newline_escaper code = "two: 1 + \\\n\n 1" assert @lex.tokenize(code) == [[:IDENTIFIER, "two"], [:ASSIGN, ":"], - [:NUMBER, "1"], ["+", "+"], [:NUMBER, "1"]] + [:NUMBER, "1"], ["+", "+"], [:NUMBER, "1"], ["\n", "\n"]] end def test_lexing diff --git a/test/unit/test_parser.rb b/test/unit/test_parser.rb index fecb18235c..dfcc4763ad 100644 --- a/test/unit/test_parser.rb +++ b/test/unit/test_parser.rb @@ -8,7 +8,7 @@ def setup def test_parsing_an_empty_string nodes = @par.parse("") - assert nodes.is_a? Expressions + assert nodes.is_a?(Expressions) assert nodes.expressions.empty? end @@ -16,45 +16,45 @@ def test_parsing_a_basic_assignment nodes = @par.parse("a: 'one'").expressions assert nodes.length == 1 assign = nodes.first - assert assign.is_a? AssignNode + assert assign.is_a?(AssignNode) assert assign.variable.literal == 'a' end def test_parsing_an_object_literal - nodes = @par.parse("{one : 1 \n two : 2}").expressions + nodes = @par.parse("{one : 1\ntwo : 2}").expressions obj = nodes.first.literal - assert obj.is_a? ObjectNode + assert obj.is_a?(ObjectNode) assert obj.properties.first.variable.literal.value == "one" assert obj.properties.last.variable.literal.value == "two" 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 + assert body.is_a?(OpNode) assert body.operator == '*' end def test_parsing_if_statement the_if = @par.parse("clap_your_hands() if happy").expressions.first - assert the_if.is_a? IfNode + assert the_if.is_a?(IfNode) assert the_if.condition.literal == 'happy' - assert the_if.body.is_a? CallNode + assert the_if.body.is_a?(CallNode) assert the_if.body.variable.literal == 'clap_your_hands' end def test_parsing_array_comprehension - nodes = @par.parse("i for x, i in [10, 9, 8, 7, 6, 5] if i % 2 is 0.").expressions - assert nodes.first.is_a? ForNode + nodes = @par.parse("i for x, i in [10, 9, 8, 7, 6, 5] when i % 2 is 0").expressions + assert nodes.first.is_a?(ForNode) assert nodes.first.body.literal == 'i' assert nodes.first.filter.operator == '===' assert nodes.first.source.literal.objects.last.literal.value == "5" end def test_parsing_comment - nodes = @par.parse("a: 1\n # comment\nb: 2").expressions - assert nodes[1].is_a? CommentNode + nodes = @par.parse("a: 1\n# comment\nb: 2").expressions + assert nodes[1].is_a?(CommentNode) end def test_parsing_inner_comments @@ -65,9 +65,9 @@ def test_parsing_inner_comments def test_parsing nodes = @par.parse(File.read('test/fixtures/generation/each.coffee')) assign = nodes.expressions[1] - assert assign.is_a? AssignNode + assert assign.is_a?(AssignNode) assert assign.variable.literal == '_' - assert assign.value.is_a? CodeNode + assert assign.value.is_a?(CodeNode) assert assign.value.params == ['obj', 'iterator', 'context'] assert nodes.compile == File.read('test/fixtures/generation/each.js') end @@ -77,10 +77,4 @@ def test_no_wrap assert nodes.compile(:no_wrap => true) == File.read('test/fixtures/generation/each_no_wrap.js') end - def test_no_wrapping_parens_around_statements - assert_raises(SyntaxError) do - @par.parse("(try thing() catch error fail().)").compile - end - end - end