diff --git a/documentation/coffee/super.coffee b/documentation/coffee/super.coffee index cc28c84d..a64eff39 100644 --- a/documentation/coffee/super.coffee +++ b/documentation/coffee/super.coffee @@ -1,16 +1,16 @@ Animal: => -Animal.prototype.move: meters => +Animal::move: meters => alert(this.name + " moved " + meters + "m.") Snake: name => this.name: name Snake extends Animal -Snake.prototype.move: => +Snake::move: => alert("Slithering...") super(5) Horse: name => this.name: name Horse extends Animal -Horse.prototype.move: => +Horse::move: => alert("Galloping...") super(45) diff --git a/documentation/index.html.erb b/documentation/index.html.erb index a396ce3a..c80b7757 100644 --- a/documentation/index.html.erb +++ b/documentation/index.html.erb @@ -467,9 +467,9 @@ coffee --print app/scripts/*.coffee > concatenation.js it's awkward to call super (the prototype object's implementation of the current function), and it's awkward to correctly set the prototype chain. CoffeeScript provides extends - to help with prototype setup, and converts - super() calls into calls against the immediate ancestor's - method of the same name. + to help with prototype setup, :: for quick access to an + object's prototype, and converts super() calls into calls against + the immediate ancestor's method of the same name.

<%= code_for('super', true) %> @@ -575,11 +575,21 @@ coffee --print app/scripts/*.coffee > concatenation.js

0.2.2 + When performing a comprehension over an object, use ino, instead + of in, which helps us generate smaller, more efficient code at + compile time. +
+ Added :: as a shorthand for saying .prototype. +
The "splat" symbol has been changed from a prefix asterisk *, to - a postfix ellipsis .... Added JavaScript's in operator, + a postfix ellipsis ... +
+ Added JavaScript's in operator, empty return statements, and empty while loops. +
Constructor functions that start with capital letters now include a safety check to make sure that the new instance of the object is returned. +
The extends keyword now functions identically to goog.inherits in Google's Closure Library.

diff --git a/examples/code.coffee b/examples/code.coffee index ca78218c..4917d0fe 100644 --- a/examples/code.coffee +++ b/examples/code.coffee @@ -141,18 +141,18 @@ aliquam erat volutpat. Ut wisi enim ad." # Inheritance and calling super. Animal: => -Animal.prototype.move: meters => +Animal::move: meters => alert(this.name + " moved " + meters + "m.") Snake: name => this.name: name Snake extends Animal -Snake.prototype.move: => +Snake::move: => alert('Slithering...') super(5) Horse: name => this.name: name Horse extends Animal -Horse.prototype.move: => +Horse::move: => alert('Galloping...') super(45) diff --git a/examples/underscore.coffee b/examples/underscore.coffee index 31881a34..96781227 100644 --- a/examples/underscore.coffee +++ b/examples/underscore.coffee @@ -39,11 +39,11 @@ # Create quick reference variables for speed access to core prototypes. - slice: Array.prototype.slice - unshift: Array.prototype.unshift - toString: Object.prototype.toString - hasOwnProperty: Object.prototype.hasOwnProperty - propertyIsEnumerable: Object.prototype.propertyIsEnumerable + slice: Array::slice + unshift: Array::unshift + toString: Object::toString + hasOwnProperty: Object::hasOwnProperty + propertyIsEnumerable: Object::propertyIsEnumerable # Current version. @@ -585,10 +585,10 @@ # Start chaining a wrapped Underscore object. - wrapper.prototype.chain: => + wrapper::chain: => this._chain: true this # Extracts the result from a wrapped and chained object. - wrapper.prototype.value: => this._wrapped + wrapper::value: => this._wrapped diff --git a/index.html b/index.html index 3f284d67..8c72bffc 100644 --- a/index.html +++ b/index.html @@ -973,23 +973,23 @@ globals = ((function() { it's awkward to call super (the prototype object's implementation of the current function), and it's awkward to correctly set the prototype chain. CoffeeScript provides extends - to help with prototype setup, and converts - super() calls into calls against the immediate ancestor's - method of the same name. + to help with prototype setup, :: for quick access to an + object's prototype, and converts super() calls into calls against + the immediate ancestor's method of the same name.

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

0.2.2 + When performing a comprehension over an object, use ino, instead + of in, which helps us generate smaller, more efficient code at + compile time. +
+ Added :: as a shorthand for saying .prototype. +
The "splat" symbol has been changed from a prefix asterisk *, to - a postfix ellipsis .... Added JavaScript's in operator, + a postfix ellipsis ... +
+ Added JavaScript's in operator, empty return statements, and empty while loops. +
Constructor functions that start with capital letters now include a safety check to make sure that the new instance of the object is returned. +
The extends keyword now functions identically to goog.inherits in Google's Closure Library.

diff --git a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage b/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage index 034d410e..a50aafae 100644 --- a/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage +++ b/lib/coffee_script/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage @@ -43,7 +43,7 @@ comment match stuff like: funcName: => … match - ([a-zA-Z0-9_?.$*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>) + ([a-zA-Z0-9_?.$:*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=>) name meta.function.coffee @@ -64,7 +64,7 @@ comment match stuff like: a => … match - ([a-zA-Z0-9_?., $*]*)\s*(=>) + ([a-zA-Z0-9_?., $:*]*)\s*(=>) name meta.inline.function.coffee @@ -214,7 +214,7 @@ match - \b([a-zA-Z$_](\w|\$)*)(\:)\s + \b([a-zA-Z$_](\w|\$|:)*)(\:)\s name variable.assignment.coffee captures diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index 0b270cfa..12567351 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -4,7 +4,7 @@ class Parser token IF ELSE UNLESS token NUMBER STRING REGEX token TRUE FALSE YES NO ON OFF -token IDENTIFIER PROPERTY_ACCESS +token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS token CODE PARAM NEW RETURN token TRY CATCH FINALLY THROW token BREAK CONTINUE @@ -234,6 +234,7 @@ rule # Accessing into an object or array, through dot or index notation. Accessor: PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) } + | PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], true) } | Index { result = val[0] } | Range { result = SliceNode.new(val[0]) } ; diff --git a/lib/coffee_script/lexer.rb b/lib/coffee_script/lexer.rb index 9e75beac..a629be28 100644 --- a/lib/coffee_script/lexer.rb +++ b/lib/coffee_script/lexer.rb @@ -88,6 +88,7 @@ module CoffeeScript tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER tag = :LEADING_WHEN if tag == :WHEN && [:OUTDENT, :INDENT, "\n"].include?(last_tag) @tokens[-1][0] = :PROPERTY_ACCESS if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2][1] == '.') + @tokens[-1][0] = :PROTOTYPE_ACCESS if tag == :IDENTIFIER && last_value == '::' token(tag, identifier) @i += identifier.length end diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 02ce4707..dbb5add3 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -324,12 +324,13 @@ module CoffeeScript class AccessorNode < Node attr_reader :name - def initialize(name) - @name = name + def initialize(name, prototype=false) + @name, @prototype = name, prototype end def compile_node(o) - write(".#{@name}") + proto = @prototype ? "prototype." : '' + write(".#{proto}#{@name}") end end @@ -416,7 +417,7 @@ module CoffeeScript # Setting the value of a local variable, or the value of an object property. class AssignNode < Node PROTO_ASSIGN = /\A(\S+)\.prototype/ - LEADING_DOT = /\A\./ + LEADING_DOT = /\A\.(prototype\.)?/ attr_reader :variable, :value, :context diff --git a/test/fixtures/execution/test_calling_super.coffee b/test/fixtures/execution/test_calling_super.coffee index 65de1b0c..33a59bd3 100644 --- a/test/fixtures/execution/test_calling_super.coffee +++ b/test/fixtures/execution/test_calling_super.coffee @@ -1,21 +1,21 @@ Base: => -Base.prototype.func: string => +Base::func: string => 'zero/' + string FirstChild: => FirstChild extends Base -FirstChild.prototype.func: string => +FirstChild::func: string => super('one/') + string SecondChild: => SecondChild extends FirstChild -SecondChild.prototype.func: string => +SecondChild::func: string => super('two/') + string ThirdChild: => this.array: [1, 2, 3] ThirdChild extends SecondChild -ThirdChild.prototype.func: string => +ThirdChild::func: string => super('three/') + string result: (new ThirdChild()).func('four')