mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
added the ability to super()
This commit is contained in:
parent
1a8311b9d0
commit
1d35910567
5 changed files with 57 additions and 15 deletions
2
TODO
2
TODO
|
@ -1,5 +1,7 @@
|
|||
TODO:
|
||||
|
||||
* Super in methods. (reserve it).
|
||||
|
||||
* Need *way* better syntax errors.
|
||||
|
||||
* Is it possible to close blocks (functions, ifs, trys) without an explicit
|
||||
|
|
|
@ -128,4 +128,12 @@ three_to_six: zero_to_nine[3, 6]
|
|||
# Multiline strings with inner quotes.
|
||||
story: "Lorem ipsum dolor \"sit\" amet, consectetuer adipiscing elit,
|
||||
sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
|
||||
aliquam erat volutpat. Ut wisi enim ad."
|
||||
aliquam erat volutpat. Ut wisi enim ad."
|
||||
|
||||
# Calling super from an overridden method.
|
||||
Greeter: => . # Create the parent object.
|
||||
Greeter.prototype.hello: name => alert('Hello ' + name). # Define a "hello" method.
|
||||
Exclaimer: name => this.name: name. # Create the child object.
|
||||
Exclaimer.prototype: new Greeter() # Set the child to inherit from the parent.
|
||||
Exclaimer.prototype.hello: => super(this.name + "!"). # The child's "hello" calls the parent's via "super".
|
||||
(new Exclaimer('Bob')).hello() # Run it.
|
||||
|
|
|
@ -10,6 +10,7 @@ token TRY CATCH FINALLY THROW
|
|||
token BREAK CONTINUE
|
||||
token FOR IN WHILE
|
||||
token SWITCH CASE DEFAULT
|
||||
token SUPER
|
||||
token NEWLINE
|
||||
token JS
|
||||
|
||||
|
@ -149,10 +150,16 @@ rule
|
|||
|
||||
# Method definition
|
||||
Code:
|
||||
ParamList "=>" Expressions "." { result = CodeNode.new(val[0], val[2]) }
|
||||
| "=>" Expressions "." { result = CodeNode.new([], val[1]) }
|
||||
ParamList "=>" CodeBody "." { result = CodeNode.new(val[0], val[2]) }
|
||||
| "=>" CodeBody "." { result = CodeNode.new([], val[1]) }
|
||||
;
|
||||
|
||||
CodeBody:
|
||||
/* nothing */ { result = Nodes.new([]) }
|
||||
| Expressions { result = val[0] }
|
||||
;
|
||||
|
||||
|
||||
ParamList:
|
||||
PARAM { result = val }
|
||||
| ParamList "," PARAM { result = val[0] << val[2] }
|
||||
|
@ -196,12 +203,17 @@ rule
|
|||
Call:
|
||||
Invocation { result = val[0] }
|
||||
| NEW Invocation { result = val[1].new_instance }
|
||||
| Super { result = val[0] }
|
||||
;
|
||||
|
||||
Invocation:
|
||||
Value "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
|
||||
;
|
||||
|
||||
Super:
|
||||
SUPER "(" ArgList ")" { result = CallNode.new(:super, val[2]) }
|
||||
;
|
||||
|
||||
# An Array.
|
||||
Array:
|
||||
"[" ArgList "]" { result = ArrayNode.new(val[1]) }
|
||||
|
|
|
@ -7,7 +7,8 @@ class Lexer
|
|||
"try", "catch", "finally", "throw",
|
||||
"break", "continue",
|
||||
"for", "in", "while",
|
||||
"switch", "case", "default"]
|
||||
"switch", "case", "default",
|
||||
"super"]
|
||||
|
||||
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
|
||||
NUMBER = /\A([0-9]+(\.[0-9]+)?)/
|
||||
|
|
|
@ -122,6 +122,8 @@ end
|
|||
# receiver.method(argument1, argument2)
|
||||
#
|
||||
class CallNode < Node
|
||||
LEADING_DOT = /\A\./
|
||||
|
||||
def initialize(variable, arguments=[])
|
||||
@variable, @arguments = variable, arguments
|
||||
end
|
||||
|
@ -131,14 +133,26 @@ class CallNode < Node
|
|||
self
|
||||
end
|
||||
|
||||
def super?
|
||||
@variable == :super
|
||||
end
|
||||
|
||||
def compile(indent, scope, opts={})
|
||||
args = @arguments.map{|a| a.compile(indent, scope, :no_paren => true) }.join(', ')
|
||||
return compile_super(args, indent, scope, opts) if super?
|
||||
prefix = @new ? "new " : ''
|
||||
"#{prefix}#{@variable.compile(indent, scope)}(#{args})"
|
||||
end
|
||||
|
||||
def compile_super(args, indent, scope, opts)
|
||||
methname = opts[:last_assign].sub(LEADING_DOT, '')
|
||||
"this.constructor.prototype.#{methname}.call(this, #{args})"
|
||||
end
|
||||
end
|
||||
|
||||
class ValueNode < Node
|
||||
attr_reader :last
|
||||
|
||||
def initialize(name, properties=[])
|
||||
@name, @properties = name, properties
|
||||
end
|
||||
|
@ -153,9 +167,11 @@ class ValueNode < Node
|
|||
end
|
||||
|
||||
def compile(indent, scope, opts={})
|
||||
[@name, @properties].flatten.map { |v|
|
||||
parts = [@name, @properties].flatten.map do |v|
|
||||
v.respond_to?(:compile) ? v.compile(indent, scope) : v.to_s
|
||||
}.join('')
|
||||
end
|
||||
@last = parts.last
|
||||
parts.join('')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -200,16 +216,18 @@ class AssignNode < Node
|
|||
end
|
||||
|
||||
def compile(indent, scope, opts={})
|
||||
value = @value.compile(indent + TAB, scope)
|
||||
name = @variable.compile(indent, scope) if @variable.respond_to?(:compile)
|
||||
last = @variable.respond_to?(:last) ? @variable.last : name
|
||||
opts = opts.merge({:assign => name, :last_assign => last})
|
||||
value = @value.compile(indent, scope, opts)
|
||||
return "#{@variable}: #{value}" if @context == :object
|
||||
name = @variable.compile(indent, scope)
|
||||
return "#{name} = #{value}" if @variable.properties?
|
||||
defined = scope.find(name)
|
||||
postfix = !defined && opts[:return] ? ";\n#{indent}return #{name}" : ''
|
||||
def_part = defined ? "" : "var #{name};\n#{indent}"
|
||||
return def_part + @value.compile(indent, scope, opts.merge(:assign => name)) if @value.custom_assign?
|
||||
def_part = defined ? name : "var #{name}"
|
||||
"#{def_part} = #{@value.compile(indent, scope)}#{postfix}"
|
||||
defined = scope.find(name)
|
||||
postfix = !defined && opts[:return] ? ";\n#{indent}return #{name}" : ''
|
||||
def_part = defined ? "" : "var #{name};\n#{indent}"
|
||||
return def_part + @value.compile(indent, scope, opts) if @value.custom_assign?
|
||||
def_part = defined ? name : "var #{name}"
|
||||
"#{def_part} = #{@value.compile(indent, scope, opts)}#{postfix}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -260,7 +278,8 @@ class CodeNode < Node
|
|||
end
|
||||
|
||||
def compile(indent, scope, opts={})
|
||||
code = @body.compile(indent + TAB, Scope.new(scope), {:return => true})
|
||||
opts = opts.merge(:return => true)
|
||||
code = @body.compile(indent + TAB, Scope.new(scope), opts)
|
||||
"function(#{@params.join(', ')}) {\n#{code}\n#{indent}}"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue