adding '::' as shorthand for '.prototype.'

This commit is contained in:
Jeremy Ashkenas 2010-01-10 16:16:59 -05:00
parent 902febb43a
commit ad18378f7e
10 changed files with 59 additions and 36 deletions

View File

@ -1,16 +1,16 @@
Animal: => Animal: =>
Animal.prototype.move: meters => Animal::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 extends Animal
Snake.prototype.move: => Snake::move: =>
alert("Slithering...") alert("Slithering...")
super(5) super(5)
Horse: name => this.name: name Horse: name => this.name: name
Horse extends Animal Horse extends Animal
Horse.prototype.move: => Horse::move: =>
alert("Galloping...") alert("Galloping...")
super(45) super(45)

View File

@ -467,9 +467,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
it's awkward to call <b>super</b> (the prototype object's it's awkward to call <b>super</b> (the prototype object's
implementation of the current function), and it's awkward to correctly implementation of the current function), and it's awkward to correctly
set the prototype chain. CoffeeScript provides <tt>extends</tt> set the prototype chain. CoffeeScript provides <tt>extends</tt>
to help with prototype setup, and converts to help with prototype setup, <tt>::</tt> for quick access to an
<tt>super()</tt> calls into calls against the immediate ancestor's object's prototype, and converts <tt>super()</tt> calls into calls against
method of the same name. the immediate ancestor's method of the same name.
</p> </p>
<%= code_for('super', true) %> <%= code_for('super', true) %>
@ -575,11 +575,21 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<p> <p>
<b class="header" style="margin-top: 20px;">0.2.2</b> <b class="header" style="margin-top: 20px;">0.2.2</b>
When performing a comprehension over an object, use <tt>ino</tt>, instead
of <tt>in</tt>, which helps us generate smaller, more efficient code at
compile time.
<br />
Added <tt>::</tt> as a shorthand for saying <tt>.prototype.</tt>
<br />
The "splat" symbol has been changed from a prefix asterisk <tt>*</tt>, to The "splat" symbol has been changed from a prefix asterisk <tt>*</tt>, to
a postfix ellipsis <tt>...</tt>. Added JavaScript's <tt>in</tt> operator, a postfix ellipsis <tt>...</tt>
<br />
Added JavaScript's <tt>in</tt> operator,
empty <tt>return</tt> statements, and empty <tt>while</tt> loops. empty <tt>return</tt> statements, and empty <tt>while</tt> loops.
<br />
Constructor functions that start with capital letters now include a Constructor functions that start with capital letters now include a
safety check to make sure that the new instance of the object is returned. safety check to make sure that the new instance of the object is returned.
<br />
The <tt>extends</tt> keyword now functions identically to <tt>goog.inherits</tt> The <tt>extends</tt> keyword now functions identically to <tt>goog.inherits</tt>
in Google's Closure Library. in Google's Closure Library.
</p> </p>

View File

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

View File

@ -39,11 +39,11 @@
# Create quick reference variables for speed access to core prototypes. # Create quick reference variables for speed access to core prototypes.
slice: Array.prototype.slice slice: Array::slice
unshift: Array.prototype.unshift unshift: Array::unshift
toString: Object.prototype.toString toString: Object::toString
hasOwnProperty: Object.prototype.hasOwnProperty hasOwnProperty: Object::hasOwnProperty
propertyIsEnumerable: Object.prototype.propertyIsEnumerable propertyIsEnumerable: Object::propertyIsEnumerable
# Current version. # Current version.
@ -585,10 +585,10 @@
# Start chaining a wrapped Underscore object. # Start chaining a wrapped Underscore object.
wrapper.prototype.chain: => wrapper::chain: =>
this._chain: true this._chain: true
this this
# Extracts the result from a wrapped and chained object. # Extracts the result from a wrapped and chained object.
wrapper.prototype.value: => this._wrapped wrapper::value: => this._wrapped

View File

@ -973,23 +973,23 @@ globals = ((function() {
it's awkward to call <b>super</b> (the prototype object's it's awkward to call <b>super</b> (the prototype object's
implementation of the current function), and it's awkward to correctly implementation of the current function), and it's awkward to correctly
set the prototype chain. CoffeeScript provides <tt>extends</tt> set the prototype chain. CoffeeScript provides <tt>extends</tt>
to help with prototype setup, and converts to help with prototype setup, <tt>::</tt> for quick access to an
<tt>super()</tt> calls into calls against the immediate ancestor's object's prototype, and converts <tt>super()</tt> calls into calls against
method of the same name. the immediate ancestor's method of the same name.
</p> </p>
<div class='code'><pre class="idle"><span class="FunctionName">Animal</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span> <div class='code'><pre class="idle"><span class="FunctionName">Animal</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
<span class="FunctionName">Animal.prototype.move</span><span class="Keyword">:</span> <span class="FunctionArgument">meters</span> <span class="Storage">=&gt;</span> Animal<span class="Keyword">:</span><span class="Keyword">:</span><span class="FunctionName">move</span><span class="Keyword">:</span> <span class="FunctionArgument">meters</span> <span class="Storage">=&gt;</span>
alert(<span class="Variable">this</span>.name <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> moved <span class="String">&quot;</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>m.<span class="String">&quot;</span></span>) alert(<span class="Variable">this</span>.name <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> moved <span class="String">&quot;</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>m.<span class="String">&quot;</span></span>)
<span class="FunctionName">Snake</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.name<span class="Keyword">:</span> name <span class="FunctionName">Snake</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.name<span class="Keyword">:</span> name
Snake <span class="Variable">extends</span> Animal Snake <span class="Variable">extends</span> Animal
<span class="FunctionName">Snake.prototype.move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span> Snake<span class="Keyword">:</span><span class="Keyword">:</span><span class="FunctionName">move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
alert(<span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>) alert(<span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>)
<span class="Variable">super</span>(<span class="Number">5</span>) <span class="Variable">super</span>(<span class="Number">5</span>)
<span class="FunctionName">Horse</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.name<span class="Keyword">:</span> name <span class="FunctionName">Horse</span><span class="Keyword">:</span> <span class="FunctionArgument">name</span> <span class="Storage">=&gt;</span> <span class="Variable">this</span>.name<span class="Keyword">:</span> name
Horse <span class="Variable">extends</span> Animal Horse <span class="Variable">extends</span> Animal
<span class="FunctionName">Horse.prototype.move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span> Horse<span class="Keyword">:</span><span class="Keyword">:</span><span class="FunctionName">move</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
alert(<span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>) alert(<span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>)
<span class="Variable">super</span>(<span class="Number">45</span>) <span class="Variable">super</span>(<span class="Number">45</span>)
@ -1265,11 +1265,21 @@ world...";
<p> <p>
<b class="header" style="margin-top: 20px;">0.2.2</b> <b class="header" style="margin-top: 20px;">0.2.2</b>
When performing a comprehension over an object, use <tt>ino</tt>, instead
of <tt>in</tt>, which helps us generate smaller, more efficient code at
compile time.
<br />
Added <tt>::</tt> as a shorthand for saying <tt>.prototype.</tt>
<br />
The "splat" symbol has been changed from a prefix asterisk <tt>*</tt>, to The "splat" symbol has been changed from a prefix asterisk <tt>*</tt>, to
a postfix ellipsis <tt>...</tt>. Added JavaScript's <tt>in</tt> operator, a postfix ellipsis <tt>...</tt>
<br />
Added JavaScript's <tt>in</tt> operator,
empty <tt>return</tt> statements, and empty <tt>while</tt> loops. empty <tt>return</tt> statements, and empty <tt>while</tt> loops.
<br />
Constructor functions that start with capital letters now include a Constructor functions that start with capital letters now include a
safety check to make sure that the new instance of the object is returned. safety check to make sure that the new instance of the object is returned.
<br />
The <tt>extends</tt> keyword now functions identically to <tt>goog.inherits</tt> The <tt>extends</tt> keyword now functions identically to <tt>goog.inherits</tt>
in Google's Closure Library. in Google's Closure Library.
</p> </p>

View File

@ -43,7 +43,7 @@
<key>comment</key> <key>comment</key>
<string>match stuff like: funcName: =&gt; … </string> <string>match stuff like: funcName: =&gt; … </string>
<key>match</key> <key>match</key>
<string>([a-zA-Z0-9_?.$*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=&gt;)</string> <string>([a-zA-Z0-9_?.$:*]*)\s*(=|:)\s*([\w,\s]*?)\s*(=&gt;)</string>
<key>name</key> <key>name</key>
<string>meta.function.coffee</string> <string>meta.function.coffee</string>
</dict> </dict>
@ -64,7 +64,7 @@
<key>comment</key> <key>comment</key>
<string>match stuff like: a =&gt; … </string> <string>match stuff like: a =&gt; … </string>
<key>match</key> <key>match</key>
<string>([a-zA-Z0-9_?., $*]*)\s*(=&gt;)</string> <string>([a-zA-Z0-9_?., $:*]*)\s*(=&gt;)</string>
<key>name</key> <key>name</key>
<string>meta.inline.function.coffee</string> <string>meta.inline.function.coffee</string>
</dict> </dict>
@ -214,7 +214,7 @@
</dict> </dict>
<dict> <dict>
<key>match</key> <key>match</key>
<string>\b([a-zA-Z$_](\w|\$)*)(\:)\s</string> <string>\b([a-zA-Z$_](\w|\$|:)*)(\:)\s</string>
<key>name</key> <key>name</key>
<string>variable.assignment.coffee</string> <string>variable.assignment.coffee</string>
<key>captures</key> <key>captures</key>

View File

@ -4,7 +4,7 @@ class Parser
token IF ELSE UNLESS token IF ELSE UNLESS
token NUMBER STRING REGEX token NUMBER STRING REGEX
token TRUE FALSE YES NO ON OFF token TRUE FALSE YES NO ON OFF
token IDENTIFIER PROPERTY_ACCESS token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS
token CODE PARAM NEW RETURN token CODE PARAM NEW RETURN
token TRY CATCH FINALLY THROW token TRY CATCH FINALLY THROW
token BREAK CONTINUE token BREAK CONTINUE
@ -234,6 +234,7 @@ rule
# Accessing into an object or array, through dot or index notation. # Accessing into an object or array, through dot or index notation.
Accessor: Accessor:
PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) } PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) }
| PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], true) }
| Index { result = val[0] } | Index { result = val[0] }
| Range { result = SliceNode.new(val[0]) } | Range { result = SliceNode.new(val[0]) }
; ;

View File

@ -88,6 +88,7 @@ module CoffeeScript
tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER tag = KEYWORDS.include?(identifier) ? identifier.upcase.to_sym : :IDENTIFIER
tag = :LEADING_WHEN if tag == :WHEN && [:OUTDENT, :INDENT, "\n"].include?(last_tag) 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] = :PROPERTY_ACCESS if tag == :IDENTIFIER && last_value == '.' && !(@tokens[-2][1] == '.')
@tokens[-1][0] = :PROTOTYPE_ACCESS if tag == :IDENTIFIER && last_value == '::'
token(tag, identifier) token(tag, identifier)
@i += identifier.length @i += identifier.length
end end

View File

@ -324,12 +324,13 @@ module CoffeeScript
class AccessorNode < Node class AccessorNode < Node
attr_reader :name attr_reader :name
def initialize(name) def initialize(name, prototype=false)
@name = name @name, @prototype = name, prototype
end end
def compile_node(o) def compile_node(o)
write(".#{@name}") proto = @prototype ? "prototype." : ''
write(".#{proto}#{@name}")
end end
end end
@ -416,7 +417,7 @@ module CoffeeScript
# Setting the value of a local variable, or the value of an object property. # Setting the value of a local variable, or the value of an object property.
class AssignNode < Node class AssignNode < Node
PROTO_ASSIGN = /\A(\S+)\.prototype/ PROTO_ASSIGN = /\A(\S+)\.prototype/
LEADING_DOT = /\A\./ LEADING_DOT = /\A\.(prototype\.)?/
attr_reader :variable, :value, :context attr_reader :variable, :value, :context

View File

@ -1,21 +1,21 @@
Base: => Base: =>
Base.prototype.func: string => Base::func: string =>
'zero/' + string 'zero/' + string
FirstChild: => FirstChild: =>
FirstChild extends Base FirstChild extends Base
FirstChild.prototype.func: string => FirstChild::func: string =>
super('one/') + string super('one/') + string
SecondChild: => SecondChild: =>
SecondChild extends FirstChild SecondChild extends FirstChild
SecondChild.prototype.func: string => SecondChild::func: string =>
super('two/') + string super('two/') + string
ThirdChild: => ThirdChild: =>
this.array: [1, 2, 3] this.array: [1, 2, 3]
ThirdChild extends SecondChild ThirdChild extends SecondChild
ThirdChild.prototype.func: string => ThirdChild::func: string =>
super('three/') + string super('three/') + string
result: (new ThirdChild()).func('four') result: (new ThirdChild()).func('four')