removing the constructor safety check -- it wasn't safe enough (Issue 36)

This commit is contained in:
Jeremy Ashkenas 2010-02-09 07:59:48 -05:00
parent 522df2a355
commit c6a6788694
4 changed files with 22 additions and 14 deletions

View File

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

View File

@ -171,11 +171,8 @@ module CoffeeScript
return "#{stmt ? '' : idt}#{node.compile(o.merge(:top => true))}#{stmt ? '' : ';'}" unless returns return "#{stmt ? '' : idt}#{node.compile(o.merge(:top => true))}#{stmt ? '' : ';'}" unless returns
# If it's a statement, the node knows how to return itself. # If it's a statement, the node knows how to return itself.
return node.compile(o.merge(:return => true)) if node.statement? return node.compile(o.merge(:return => true)) if node.statement?
# If it's not part of a constructor, we can just return the value of the expression. # Otherwise, we can just return the value of the expression.
return "#{idt}return #{node.compile(o)};" unless o[:scope].function && o[:scope].function.constructor? return "#{idt}return #{node.compile(o)};"
# It's the last line of a constructor, add a safety check.
temp = o[:scope].free_variable
"#{idt}#{temp} = #{node.compile(o)};\n#{idt}return #{o[:scope].function.name} === this.constructor ? this : #{temp};"
end end
end end

View File

@ -220,11 +220,9 @@ Expressions: exports.Expressions: inherit Node, {
return (if stmt then '' else @idt()) + node.compile(merge(o, {top: true})) + (if stmt then '' else ';') unless returns return (if stmt then '' else @idt()) + node.compile(merge(o, {top: true})) + (if stmt then '' else ';') unless returns
# If it's a statement, the node knows how to return itself. # If it's a statement, the node knows how to return itself.
return node.compile(merge(o, {returns: true})) if node.is_statement() return node.compile(merge(o, {returns: true})) if node.is_statement()
# If it's not part of a constructor, we can just return the value of the expression. # Otherwise, we can just return the value of the expression.
return @idt() + 'return ' + node.compile(o) unless o.scope.method?.is_constructor() return @idt() + 'return ' + node.compile(o)
# It's the last line of a constructor, add a safety check.
temp: o.scope.free_variable()
@idt() + temp + ' = ' + node.compile(o) + ";\n" + @idt() + "return " + o.scope.method.name + ' === this.constructor ? this : ' + temp + ';'
} }
# Wrap up a node as an Expressions, unless it already is one. # Wrap up a node as an Expressions, unless it already is one.

View File

@ -14,6 +14,7 @@ SecondChild::func: (string) ->
ThirdChild: -> ThirdChild: ->
@array: [1, 2, 3] @array: [1, 2, 3]
this
ThirdChild extends SecondChild ThirdChild extends SecondChild
ThirdChild::func: (string) -> ThirdChild::func: (string) ->
super('three/') + string super('three/') + string
@ -25,12 +26,15 @@ puts result is 'zero/one/two/three/four'
TopClass: (arg) -> TopClass: (arg) ->
@prop: 'top-' + arg @prop: 'top-' + arg
this
SuperClass: (arg) -> SuperClass: (arg) ->
super 'super-' + arg super 'super-' + arg
this
SubClass: -> SubClass: ->
super 'sub' super 'sub'
this
SuperClass extends TopClass SuperClass extends TopClass
SubClass extends SuperClass SubClass extends SuperClass