From 64879cdc66837978442fbc4a1ba7faa90663cd45 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Wed, 23 Dec 2009 20:24:55 -0500 Subject: [PATCH] added yes, no, on and off as boolean aliases and a nice aliases section to the docs --- documentation/cs/aliases.cs | 5 ++ documentation/cs/embedded.cs | 5 +- documentation/index.html.erb | 34 ++++----- documentation/js/aliases.js | 12 ++++ documentation/js/embedded.js | 9 +-- index.html | 70 +++++++++++-------- .../Syntaxes/CoffeeScript.tmLanguage | 4 +- lib/coffee_script/grammar.y | 11 +-- lib/coffee_script/lexer.rb | 4 +- lib/coffee_script/nodes.rb | 4 +- 10 files changed, 95 insertions(+), 63 deletions(-) create mode 100644 documentation/cs/aliases.cs create mode 100644 documentation/js/aliases.js diff --git a/documentation/cs/aliases.cs b/documentation/cs/aliases.cs new file mode 100644 index 00000000..3bbbb490 --- /dev/null +++ b/documentation/cs/aliases.cs @@ -0,0 +1,5 @@ +launch() if ignition is on + +volume: 10 if band aint spinal_tap + +let_the_wild_rumpus_begin() unless answer is no diff --git a/documentation/cs/embedded.cs b/documentation/cs/embedded.cs index 5a4f0d24..400c15b4 100644 --- a/documentation/cs/embedded.cs +++ b/documentation/cs/embedded.cs @@ -1,3 +1,4 @@ -js: => `alert("Hello JavaScript");`. +hi: `function() { + return [document.title, "Hello JavaScript"].join(": "); +}` -js() if 10 > 9 \ No newline at end of file diff --git a/documentation/index.html.erb b/documentation/index.html.erb index b2ea5486..eba228f5 100644 --- a/documentation/index.html.erb +++ b/documentation/index.html.erb @@ -19,7 +19,7 @@ - CoffeeScript, briefly... + CoffeeScript @@ -33,7 +33,7 @@ CoffeeScript is a little language that compiles into JavaScript. Think of it as JavaScript's less ostentatious kid brother — the same genes, the same accent, but a different sense of style. Apart from a handful of - bonus goodies, statements in CoffeeScript correspond one-to-one with their + bonus goodies, statements in CoffeeScript correspond one-to-one with their equivalent in JavaScript, it's just another way of saying it.

@@ -232,7 +232,7 @@ coffee-script --print app/scripts/*.cs > concatenation.js

CoffeeScript includes the conditional assignment operators: ||:, which only assigns a value to a variable if the variable's current value - is falsy, and &&:, which will only replace the value of + is falsy, and &&:, which only replaces the value of truthy variables.

@@ -257,15 +257,15 @@ coffee-script --print app/scripts/*.cs > concatenation.js

<%= code_for('while') %>

- Other JavaScript loops, such as for loops and do-while loops - can be mimicked by variations on while, but the hope is that you - won't need to do that with CoffeeScript, either because you're using + Other JavaScript loops, such as for loops and do-while loops + can be mimicked by variations on while, but the hope is that you + won't need to do that with CoffeeScript, either because you're using each (forEach) style iterators, or...

Array Comprehensions - For your looping needs, CoffeeScript provides array comprehensions + 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. Unlike for loops, array comprehensions are expressions, and can be returned @@ -287,7 +287,7 @@ coffee-script --print app/scripts/*.cs > concatenation.js JavaScript's prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript's prototypes: - Base2, + Base2, Prototype.js, JS.Class, etc.

@@ -298,24 +298,26 @@ coffee-script --print app/scripts/*.cs > concatenation.js If you ever need to interpolate literal JavaScript snippets, you can use backticks to pass JavaScript straight through.

- <%= code_for('embedded', true) %> + <%= code_for('embedded', 'hi()') %>

Aliases - Because the == operator frequently causes undesirable coercion, + Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. -

-

- is also compiles into ===, + In addition, is compiles into ===, and aint into !==.

- + As in YAML, on and yes + are the same as boolean true, while off and no are boolean false.

- - +

+ For single-line statements, unless can be used as the inverse of if. +

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

Switch/Case/Else Switch statements in JavaScript are fundamentally broken. You can only diff --git a/documentation/js/aliases.js b/documentation/js/aliases.js new file mode 100644 index 00000000..f30e00ea --- /dev/null +++ b/documentation/js/aliases.js @@ -0,0 +1,12 @@ +(function(){ + if (ignition === true) { + launch(); + } + var volume; + if (band !== spinal_tap) { + volume = 10; + } + if (!(answer === false)) { + let_the_wild_rumpus_begin(); + } +})(); \ No newline at end of file diff --git a/documentation/js/embedded.js b/documentation/js/embedded.js index 4686b688..3c16b185 100644 --- a/documentation/js/embedded.js +++ b/documentation/js/embedded.js @@ -1,8 +1,5 @@ (function(){ - var js = function() { - return alert("Hello JavaScript"); - }; - if (10 > 9) { - js(); - } + var hi = function() { + return [document.title, "Hello JavaScript"].join(": "); +}; })(); \ No newline at end of file diff --git a/index.html b/index.html index 4417434c..6f5e195c 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ - CoffeeScript, briefly... + CoffeeScript @@ -19,7 +19,7 @@ CoffeeScript is a little language that compiles into JavaScript. Think of it as JavaScript's less ostentatious kid brother — the same genes, the same accent, but a different sense of style. Apart from a handful of - bonus goodies, statements in CoffeeScript correspond one-to-one with their + bonus goodies, statements in CoffeeScript correspond one-to-one with their equivalent in JavaScript, it's just another way of saying it.

@@ -363,7 +363,7 @@ var new_num = change_numbers(); date: if friday then sue else jill. -expensive ||= do_the_math() +expensive ||: do_the_math()
var mood;
 if (singing) {
   mood = greatly_improved;
@@ -378,7 +378,7 @@ expensive = expensive ||
       CoffeeScript includes the conditional assignment operators: ||:,
       which only assigns a value to a variable if the variable's current value
-      is falsy, and &&:, which will only replace the value of
+      is falsy, and &&:, which only replaces the value of
       truthy variables.
     

@@ -444,15 +444,15 @@ var eldest = 24 > 21 ? "Liz" : "Ike"; }

- Other JavaScript loops, such as for loops and do-while loops - can be mimicked by variations on while, but the hope is that you - won't need to do that with CoffeeScript, either because you're using + Other JavaScript loops, such as for loops and do-while loops + can be mimicked by variations on while, but the hope is that you + won't need to do that with CoffeeScript, either because you're using each (forEach) style iterators, or...

Array Comprehensions - For your looping needs, CoffeeScript provides array comprehensions + 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. Unlike for loops, array comprehensions are expressions, and can be returned @@ -502,7 +502,7 @@ var three_to_six = nums.slice(3, 6 + 1); JavaScript's prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript's prototypes: - Base2, + Base2, Prototype.js, JS.Class, etc.

@@ -584,39 +584,51 @@ tom.move(); If you ever need to interpolate literal JavaScript snippets, you can use backticks to pass JavaScript straight through.

-
js: => `alert("Hello JavaScript");`.
+    
hi: `function() {
+  return [document.title, "Hello JavaScript"].join(": ");
+}`
 
-js() if 10 > 9
-
var js = function() {
-  return alert("Hello JavaScript");
+
var hi = function() {
+return [document.title, "Hello JavaScript"].join(": ");
 };
-if (10 > 9) {
-  js();
-}
-

+;alert(hi());'>run: hi()

Aliases - Because the == operator frequently causes undesirable coercion, + Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. -

-

- is also compiles into ===, + In addition, is compiles into ===, and aint into !==.

- + As in YAML, on and yes + are the same as boolean true, while off and no are boolean false.

- - +

+ For single-line statements, unless can be used as the inverse of if. +

+
launch() if ignition is on
+
+volume: 10 if band aint spinal_tap
+
+let_the_wild_rumpus_begin() unless answer is no
+
if (ignition === true) {
+  launch();
+}
+var volume;
+if (band !== spinal_tap) {
+  volume = 10;
+}
+if (!(answer === false)) {
+  let_the_wild_rumpus_begin();
+}
+

+

Switch/Case/Else Switch statements in JavaScript are fundamentally broken. You can only diff --git a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage b/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage index b788c281..cb348dcc 100644 --- a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage +++ b/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage @@ -211,13 +211,13 @@ match - \btrue\b + \b(true|on|yes)\b name constant.language.boolean.true.cs match - \bfalse\b + \b(false|off|no)\b name constant.language.boolean.false.cs diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index ef00e4c8..d07ad289 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -3,7 +3,7 @@ class Parser # Declare tokens produced by the lexer token IF ELSE THEN UNLESS token NUMBER STRING REGEX -token TRUE FALSE NULL +token TRUE FALSE YES NO ON OFF token IDENTIFIER PROPERTY_ACCESS token CODE PARAM NEW RETURN token TRY CATCH FINALLY THROW @@ -102,11 +102,14 @@ rule | STRING { result = LiteralNode.new(val[0]) } | JS { result = LiteralNode.new(val[0]) } | REGEX { result = LiteralNode.new(val[0]) } - | TRUE { result = LiteralNode.new(true) } - | FALSE { result = LiteralNode.new(false) } - | NULL { result = LiteralNode.new(nil) } | BREAK { result = LiteralNode.new(val[0]) } | CONTINUE { result = LiteralNode.new(val[0]) } + | TRUE { result = LiteralNode.new(true) } + | FALSE { result = LiteralNode.new(false) } + | YES { result = LiteralNode.new(true) } + | NO { result = LiteralNode.new(false) } + | ON { result = LiteralNode.new(true) } + | OFF { result = LiteralNode.new(false) } ; # Assignment to a variable. diff --git a/lib/coffee_script/lexer.rb b/lib/coffee_script/lexer.rb index 5ea07844..b511d0a7 100644 --- a/lib/coffee_script/lexer.rb +++ b/lib/coffee_script/lexer.rb @@ -7,7 +7,7 @@ module CoffeeScript # The list of keywords passed verbatim to the parser. KEYWORDS = ["if", "else", "then", "unless", - "true", "false", "null", + "true", "false", "yes", "no", "on", "off", "and", "or", "is", "aint", "not", "new", "return", "try", "catch", "finally", "throw", @@ -21,7 +21,7 @@ module CoffeeScript IDENTIFIER = /\A([a-zA-Z$_]\w*)/ NUMBER = /\A\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b/i STRING = /\A(""|''|"(.*?)[^\\]"|'(.*?)[^\\]')/m - JS = /\A(`(.*?)`)/ + JS = /\A(``|`(.*?)[^\\]`)/m OPERATOR = /\A([+\*&|\/\-%=<>:]+)/ WHITESPACE = /\A([ \t\r]+)/ NEWLINE = /\A(\n+)/ diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 7328e402..1b7484ff 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -601,7 +601,7 @@ module CoffeeScript @body = body && body.unwrap @else_body = else_body && else_body.unwrap @tags = tags - @condition = OpNode.new("!", @condition) if @tags[:invert] + @condition = OpNode.new("!", ParentheticalNode.new(@condition)) if @tags[:invert] end def <<(else_body) @@ -656,7 +656,7 @@ module CoffeeScript def compile_statement(o) indent = o[:indent] o[:indent] += TAB - if_part = "if (#{@condition.compile(o.merge(:no_paren => true))}) {\n#{Expressions.wrap(@body).compile(o)}\n#{indent}}" + if_part = "if (#{@condition.compile(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))}" :